gratifiant > comp.lang.* > comp.lang.python

lacsaP Patatetom (25/10/2019, 22h04)
bonjour,

j'ai un petit script python censé ouvrir un fichier journal et afficher son contenu mais comme vous le voyez, une erreur liée à l'encodage survient :

-----------------------

import fileinput
import sys
try:
source = sys.argv[1:]
except IndexError:
source = None
for line in fileinput.input(source):
print(line.strip())

-----------------------

python3.7.4 myscript.py myfile.log
Traceback (most recent call last):
....
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe8 in position 799: invalid continuation byte

python3.7.4 myscript.py < myfile.log
Traceback (most recent call last):
....
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe8 in position 799: invalid continuation byte

-----------------------

j'ajoute le crochet d'encodage pour dépasser l'erreur mais cette fois,le script réagit différemment selon l'entrée utilisée :

-----------------------

import fileinput
import sys
try:
source = sys.argv[1:]
except IndexError:
source = None
for line in fileinput.input(source, openhook=fileinput.hook_encoded("utf-8", "ignore")):
print(line.strip())

-----------------------

python3.7.4 myscript.py myfile.log
first line of myfile.log
....
last line of myfile.log

python3.7.4 myscript.py < myfile.log
Traceback (most recent call last):
....
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe8 in position 799: invalid continuation byte

python3.7.4 myscript.py /dev/stdin < myfile.log
first line of myfile.log
....
last line of myfile.log

python3.7.4 myscript.py - < myfile.log
Traceback (most recent call last):
....
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe8 in position 799: invalid continuation byte

-----------------------

quelqu'un aurait-il une explication et/ou une solution ?
Jo Engo (26/10/2019, 09h43)
Le Fri, 25 Oct 2019 13:04:57 -0700, lacsaP Patatetom a écrit :

> python3.7.4 myscript.py myfile.log Traceback (most recent call last):
> ...
> UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe8 in position
> 799: invalid continuation byte


Tu as un caractère non-UTF8 dans le fichier que tu parse (à la position
799 et il s'agit du caractère 0xE8
lacsaP Patatetom (26/10/2019, 17h15)
Le samedi 26 octobre 2019 09:43:05 UTC+2, Jo Engo a écrit :
> Le Fri, 25 Oct 2019 13:04:57 -0700, lacsaP Patatetom a écrit :
> Tu as un caractère non-UTF8 dans le fichier que tu parse (à la position
> 799 et il s'agit du caractère 0xE8
> --
> Qu'est-ce qu'un adulte ? Un enfant gonflé d'âge.
> -+- Simone de Beauvoir -+-


Oui, et c'est pour cela que j'ai introduit le hook dans le "second" script.

celui-ci fonctionne lorsque le fichier journal est passé en paramètre, mais pas lorsqu'il passé sur l'entrée standard...
Jo Engo (27/10/2019, 09h40)
Le Sat, 26 Oct 2019 08:15:34 -0700, lacsaP Patatetom a écrit :

> celui-ci fonctionne lorsque le fichier journal est passé en paramètre,
> mais pas lorsqu'il passé sur l'entrée standard...


Oui j'ai vu, mes excuse donc. Au risque de répondre encore à côté de la
plaque, 1 question et 1 suggestion qui n'a rien à voir avec la question

Question : où dans le fichier se situe le byte erroné ? (au milieu ou à
la fin ?) si c'est à la fin ça peut expliquer la différence de taritement

Suggestion

Comme tu semble attendre de tels problèmes pourquoi ne traites-tu pas le
fichier en raw (en 8 bits, sans tenir compte d'*aucun* caractères utf8)
lacsaP Patatetom (27/10/2019, 10h04)
Le dimanche 27 octobre 2019 08:40:28 UTC+1, Jo Engo a écrit :
[..]
> --
> Le trop de promptitude à l'erreur nous expose.
> -+- Pierre Corneille -+-


il semblerait que le problème soit connu :
si sys.stdin est utilisé par fileinput alors le hook n'est pas appliqué, ce qui explique la différence de comportement...
lacsaP Patatetom (27/10/2019, 10h08)
Le dimanche 27 octobre 2019 09:04:41 UTC+1, lacsaP Patatetom a écrit :
> Le dimanche 27 octobre 2019 08:40:28 UTC+1, Jo Engo a écrit :
> il semblerait que le problème soit connu :
> si sys.stdin est utilisé par fileinput alors le hook n'est pas appliqué, ce qui explique la différence de comportement...


le script ci-dessous fonctionne dans tous les cas :

import io
import fileinput
import sys
try:
source = sys.argv[1:]
except IndexError:
source = None
sys.stdin = io.TextIOWrapper(sys.stdin.buffer, errors='ignore')
for line in fileinput.input(source, openhook=fileinput.hook_encoded('utf-8', 'ignore')):
print(line.strip())
lacsaP Patatetom (27/10/2019, 10h16)
Le dimanche 27 octobre 2019 09:08:22 UTC+1, lacsaP Patatetom a écrit :
[..]
> sys.stdin = io.TextIOWrapper(sys.stdin.buffer, errors='ignore')
> for line in fileinput.input(source, openhook=fileinput.hook_encoded('utf-8', 'ignore')):
> print(line.strip())


la variable d'environnement PYTHONIOENCODING positionnée à UTF8:ignore (PYTHONIOENCODING=UTF8:ignore) permet aussi de contourner l'erreur liée à l'utilisation de sys.stdin