Je dispose d'un fichier texte dont l'éditeur (la Commission des opérations de bourse des États-Unis) affirme qu'il est codé en UTF-8 ( https://www.sec.gov/files/aqfs.pdf section 4). Je traite les lignes avec le code suivant :
def tags(filename):
"""Yield Tag instances from tag.txt."""
with codecs.open(filename, 'r', encoding='utf-8', errors='strict') as f:
fields = f.readline().strip().split('\t')
for line in f.readlines():
yield process_tag_record(fields, line)
Je reçois l'erreur suivante :
Traceback (most recent call last):
File "/home/randm/Projects/finance/secxbrl.py", line 151, in <module>
main()
File "/home/randm/Projects/finance/secxbrl.py", line 143, in main
all_tags = list(tags("tag.txt"))
File "/home/randm/Projects/finance/secxbrl.py", line 109, in tags
content = f.read()
File "/home/randm/Libraries/anaconda3/lib/python3.6/codecs.py", line 698, in read
return self.reader.read(size)
File "/home/randm/Libraries/anaconda3/lib/python3.6/codecs.py", line 501, in read
newchars, decodedbytes = self.decode(data, self.errors)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xad in position 3583587: invalid start byte
Étant donné que je ne peux probablement pas retourner à la SEC et lui dire qu'elle a des fichiers qui ne semblent pas être encodés en UTF-8, comment dois-je déboguer et attraper cette erreur ?
Ce que j'ai essayé
J'ai fait un hexdump du fichier et j'ai trouvé que le texte incriminé était le texte "SUPPLEMENTAL DISCLOSURE OF NON�CASH INVESTING". Si je décode l'octet incriminé en tant que point de code hexadécimal (c'est-à-dire "U+00AD"), cela a du sens dans le contexte puisqu'il s'agit du tiret doux. Mais ce qui suit ne semble pas fonctionner :
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> b"\x41".decode("utf-8")
'A'
>>> b"\xad".decode("utf-8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec cant decode byte 0xad in position 0: invalid start byte
>>> b"\xc2ad".decode("utf-8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec cant decode byte 0xc2 in position 0: invalid continuation byte
J'ai utilisé errors='replace'
qui semble passer. Mais j'aimerais comprendre ce qui va se passer si j'essaie d'insérer cela dans une base de données.
Modifié pour ajouter hexdump :
0036ae40 31 09 09 09 09 53 55 50 50 4c 45 4d 45 4e 54 41 |1....SUPPLEMENTA|
0036ae50 4c 20 44 49 53 43 4c 4f 53 55 52 45 20 4f 46 20 |L DISCLOSURE OF |
0036ae60 4e 4f 4e ad 43 41 53 48 20 49 4e 56 45 53 54 49 |NON.CASH INVESTI|
0036ae70 4e 47 20 41 4e 44 20 46 49 4e 41 4e 43 49 4e 47 |NG AND FINANCING|
0036ae80 20 41 43 54 49 56 49 54 49 45 53 3a 09 0a 50 72 | ACTIVITIES:..Pr|