Проблема в том, что вы не знаете, какие кодировки используются для писем, не относящихся к ASCII, поэтому вы просто хотите их пропустить.
Но ваш код пытается декодировать их с использованием кодировки по умолчанию, и затем решает, следует ли их пропустить. Вот что значит открыть файл в текстовом режиме, например:
with open('emails.csv') as csv_file:
for line in csv_file:
Поскольку эта кодировка по умолчанию - UTF-8, как только вы столкнетесь с чем-то, закодированным в другой кодировке, несовместимой с UTF-8, вы получите ошибку.
Вместо этого самый простой способ изменить это - открыть файл в двоичном режиме. Затем вы можете декодировать только те строки, которые решили сохранить:
with open('emails.csv', 'rb') as csv_file:
for line in csv_file:
if(is_ascii(line)):
line = line.decode('ascii')
with open('result.csv', 'a') as output_file:
output_file.write(line)
… или просто оставайтесь с байтами весь путь, открыв также выходной файл в двоичном режиме:
with open('emails.csv', 'rb') as csv_file:
for line in csv_file:
if(is_ascii(line)):
with open('result.csv', 'ab') as output_file:
output_file.write(line)
В любом случае вам придется изменить функцию isascii
, потому что bytes
- это последовательность целых чисел от 0 до 255, а не последовательность символов, поэтому вы не можете (и не нуждаетесь в этом) к) звоните ord
:
def is_ascii(s):
return all(c < 128 for c in s)
Существует потенциальная проблема. Я думаю, что у вас все будет хорошо, но вы должны продумать это (и протестировать все, что нужно для тестирования) В то время как файловые объекты в текстовом режиме автоматически обрабатывают не-Unix переводы строк, файлы в двоичном режиме этого не делают.
Если у вас есть классические файлы Mac (pre-OS X) прошлого века с окончаниями \r
, ваш код работать не будет. \r
вообще не будет рассматриваться как перевод строки, поэтому весь файл будет выглядеть как одна огромная строка. Если у вас нет таких файлов, я бы об этом не беспокоился.
Но если у вас есть только файлы, отличные от Unix, это Windows (или DOS) с \r\n
, все будет в порядке. \r
будет обрабатываться как часть строки, а не как часть новой строки, но это не будет иметь значения для вашего кода (ord('\r') < 128
, и, кроме того, все, что вы делаете, это пишете целую строку байтов сразу), так что все будет работать.