Ошибка Unicode при выводе вывода python script в файл
Это код:
print '"' + title.decode('utf-8', errors='ignore') + '",' \
' "' + title.decode('utf-8', errors='ignore') + '", ' \
'"' + desc.decode('utf-8', errors='ignore') + '")'
title и desc возвращаются Beautiful Soup 3 (p [0].text и p [0].prettify), и, насколько я могу понять из документации BeautifulSoup3, кодируется UTF-8.
Если я запустил
python.exe script.py > out.txt
Я получаю следующую ошибку:
Traceback (most recent call last):
File "script.py", line 70, in <module>
'"' + desc.decode('utf-8', errors='ignore') + '")'
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf8' in position 264
: ordinal not in range(128)
Однако, если я запустил
python.exe script.py
Я не ошибаюсь. Это происходит только в том случае, если указан выходной файл.
Как получить хорошие данные UTF-8 в выходном файле?
Ответы
Ответ 1
Вы можете использовать модуль кодеков для записи данных в формате Unicode в файл
import codecs
file = codecs.open("out.txt", "w", "utf-8")
file.write(something)
'print' выводится на стандартный вывод, и если ваша консоль не поддерживает utf-8, это может вызвать такую ошибку, даже если вы передаете stdout в файл.
Ответ 2
Поведение Windows в этом случае немного сложнее. Вы должны слушать другие советы и внутренне использовать unicode для строк и декодировать во время ввода.
На ваш вопрос вам нужно напечатать закодированные строки (только вы знаете, какая кодировка!) в случае перенаправления stdout, но вы должны печатать строки unicode в случае простого вывода на экран (а python или windows обрабатывает конверсию в правильное кодирование).
Я рекомендую структурировать ваш script следующим образом:
# -*- coding: utf-8 -*-
import sys, codecs
# set up output encoding
if not sys.stdout.isatty():
# here you can set encoding for your 'out.txt' file
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
# next, you will print all strings in unicode
print u"Unicode string ěščřžý"
Обновление: см. также другой аналогичный вопрос: Установка правильной кодировки при отправке stdout трубопровода в Python
Ответ 3
Нет смысла конвертировать текст в Юникод, чтобы распечатать его. Работайте со своими данными в юникоде, преобразуйте его в некоторую кодировку для вывода.
Вместо этого ваш код: вы находитесь на python 2, поэтому ваш тип строки по умолчанию (str
) является байтовым. В вашем заявлении вы начинаете с некоторых строк байтов, закодированных в utf, конвертируете их в Юникод, окружаете их кавычками (регулярные str
, которые принуждаются к юникоду для объединения в одну строку). Затем вы передаете эту строку юникода в print
, которая подталкивает ее к sys.stdout
. Для этого необходимо превратить его в байты. Если вы пишете на консоль Windows, он может каким-то образом договориться, но если вы перенаправляетесь на обычный немой файл, он возвращается на ascii и жалуется, потому что нет никакого способа сделать это без потерь.
Решение. Не указывайте print
строку юникода. "закодируйте" его сами по своему выбору:
print "Latin-1:", "unicode über alles!".decode('utf-8').encode('latin-1')
print "Utf-8:", "unicode über alles!".decode('utf-8').encode('utf-8')
print "Windows:", "unicode über alles!".decode('utf-8').encode('cp1252')
Все это должно работать без жалобы при перенаправлении. Вероятно, он не будет выглядеть правильно на вашем экране, но откройте выходной файл с помощью Notepad или что-то еще и посмотрите, установлен ли ваш редактор для просмотра формата. (Utf-8 является единственным, у которого есть надежда на обнаружение. Cp1252 - вероятный Windows по умолчанию).
Как только вы получите это, очистите свой код и не используйте print для вывода файла. Используйте модуль codecs
и открывайте файлы с codecs.open
, а не открытыми.
PS. Если вы декодируете строку utf-8
, преобразование в unicode должно быть без потерь: вам не нужен флаг errors=ignore
. Это подходит, если вы конвертируете в ascii или Latin-2 или что-то еще, и хотите просто отбросить символы, которые не существуют в целевой кодовой странице.
Ответ 4
Проблема: если вы работаете в Windows:
python.exe script.py
Будет действовать следующее:
sys.stdout.encoding: utf-8
sys.stdout.isatty(): True
Но если вы запустите:
python.exe script.py > out.txt
у вас действительно будет это:
sys.stdout.encoding: cp1252
sys.stdout.isatty(): False
Итак, возможное решение (В ПИТОНЕ> 3.7):
import sys
if not sys.stdout.isatty():
sys.stdout.reconfigure(encoding='utf-8')
print '"' + title.decode('utf-8', errors='ignore') + '",' \
' "' + title.decode('utf-8', errors='ignore') + '", ' \
'"' + desc.decode('utf-8', errors='ignore') + '")'
Смотрите также: Как установить кодировку sys.stdout в Python 3?