Проблема в том, что некоторые файлы в ваших zip-файлах имеют кодировку, отличную от UTF-8. Вот упрощенный пример того, что происходит.
>>> # Make a string of csv-like rows.
>>> rows = 'h1,h2\nhello,world\nßäæ,öë\n'
>>> # Encode the data with an encoding that isn't UTF-8
>>> # (cp1252 is common on Windows machines)
>>> bs = rows.encode('cp1252')
>>> # Load the encoded bytes into a file-like object
>>> bio = io.BytesIO(bs)
>>> bio.seek(0)
0
>>> # Load the file-like object into a TextIOWrapper
>>> w = io.TextIOWrapper(bio)
>>> w.seek(0)
0
>>> # Pass the TextIOWrapper to a csv reader and read it
>>> reader = csv.reader(w)
>>> for row in reader:print(row)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/kev/virtual-envs/so38/lib/python3.8/codecs.py", line 322, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xdf in position 18: invalid continuation byte
Решение состоит в том, чтобы передать encoding
аргумент TextIOWrapper
, чтобы данные были правильно декодированы:
>>> bio = io.BytesIO(bs)
>>> bio.seek(0)
0
>>> # Tell TextIOWrapper these bytes are cp1252!
>>> w = io.TextIOWrapper(bio, encoding='cp1252')
>>> w.seek(0)
0
>>> reader = csv.reader(w)
>>> for row in reader:print(row)
...
['h1', 'h2']
['hello', 'world']
['ßäæ', 'öë']
Существует еще одна проблема - вам нужно знать, какую кодировку передать на TextIOWrapper
. К сожалению, нет 100% точного способа определения кодировки файла. Вы можете догадаться (все эти файлы получены от Windows пользователей в Engli sh -оговорящих * стран, поэтому cp1252 является вероятным решением), или вы можете использовать такие инструменты, как chardet угадать для вас.
* Модуль codecs в стандартной библиотеке имеет список кодеков, доступных в Python и человеческих языках, которые они используют. связаны с.