Вы используете 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