Python, кодеки, file.writelines (), UnicodeDecodeError - PullRequest
0 голосов
/ 20 ноября 2011

Не знаю, как решить UnicodeDecodeError:

Я не могу записать текст в файл -> UnicodeDecodeError о символе â = '0xe2'.

1) â = '0xe2' символ наверняка не существует в этой строке

2) re.search не удалось найти â символ в строке, которую я пытаюсь написать file.writelines(string)

3) в открытии файла определен errors='replace', поэтому file.writelines() не должен жаловаться на символьные ошибки.

File=codecs.open(fname, 'w','utf-8', errors='replace')

lines=smart_str( lines, 'utf-8', strings_only=False, errors='replace' )
# lines is 'some webpage text after BeautifulSoup.prettify which does not contain letter â ='0xe2', which is converted with Django smart_str to string'

FileA.writelines(lines) #gives UnicodeDecodeError : 'ascii' codec can't decode byte 0xe2 in position 9637: ordinal not in range(128).

myre = re.compile(r'0xe2', re.UNICODE) # letter   â = '0xe2'
print re.search(myre, lines) #gives None
linessub=myre.sub('', lines)
print re.search(myre, linessub)  #gives None

FileA.writelines(lines) #gives UnicodeDecodeError : 'ascii' codec can't decode byte 0xe2 in position 9637: ordinal not in range(128).

1 Ответ

3 голосов
/ 20 ноября 2011

Вы используете codecs.open, поэтому ваш файловый объект ожидает строки Unicode, а не байтовые строки.

Смысл использования этой функции в том, что вам не нужно самостоятельно кодировать строки перед записью их вфайл.Вы пишете строки в кодировке Unicode, и объект file будет внутренне их кодировать.

Похоже, smart_str возвращает строки в кодировке UTF-8 (если вы передаете ему имя кодировки).Если вы передадите это файловому объекту с поддержкой кодеков, который ожидает Unicode, он сначала попытается декодировать строки байтов обратно в Unicode.Поскольку он не будет знать кодировку переданной строки, он будет использовать ascii.И вот откуда возникает ошибка, потому что строка не ascii, это UTF-8:

UnicodeDecodeError : 'ascii' codec can't decode...

Итак, вы хотите пропустить этап кодирования, выполняемый smart_str, и просто записать строки юникода вfile, или переключитесь с codecs.open() на обычный open(), который работает с байтами и, как таковой, ожидает уже закодированные байтовые строки.

Кстати, ваш тест на существование символа 0xE2 не будет работать.Во-первых, вы используете r'0xe2' в качестве шаблона, который представляет собой просто строку из 4 символов, а не один символ 0xE2.Во-вторых, вам не нужно re для чего-то простого.Просто попробуйте это:

print '\xe2' in your_str
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...