Откройте файл в двоичном режиме (mode="rb"
) и попробуйте декодировать каждую строку как UTF-8.Если вы получите UnicodeDecodeError
, декодируйте его как другую кодировку.Добавьте каждую декодированную строку в список, а затем вызовите csv.reader
или csv.DictReader
(оба они принимают списки строк, а не только файловые объекты).
Вместо жесткого кодирования, для которого требуется резервное кодирование, может быть лучше использовать chardet.detect
из библиотеки chardet
, чтобы угадать кодировку каждой строки, если вы не можете декодировать ее как UTF-8
import codec
my_csv = "some/path/to/your_file.csv"
lines = []
with open(my_csv, "rb") as f:
for line in f:
detected_encoding = codec.detect(line)["encoding"]
try:
line = line.decode("utf-8")
except UnicodeDecodeError as e:
line = line.decode(detected_encoding)
lines.append(line)
reader = csv.DictReader(lines)
for row in reader:
do_stuff(row)
Если вы хотите жестко закодировать резервную кодировку и не хотите использовать chardet
(есть веская причина, не всегда это точно), вы можете просто заменить переменную detected_encoding
с "Windows-1251"
в приведенном выше коде.
Вы можете установить chardet
с
pip install chardet
Вы можете проверить свои предположения о том, какие строки закодированы с какой кодировкой, выполнив
from collections import Counter
with open(my_csv_file, "rb") as f:
encodings = Counter(chardet.detect(line)["encoding"] for line in f)
print(encodings)
В моем случае запуск chardet
для всего файла обнаружил неправильную кодировку.Запуск его в каждой строке обнаруживал кучу кодировок, но второй наиболее распространенной (после ascii
) была правильная кодировка, которую мне нужно было использовать для чтения всего файла.
Google Chrome использует Compact Encoding Detection библиотека для определения кодировки, и она может быть более надежной, чем chardet, но она написана на C ++ вместо Python.