- Проблемы с кодировкой в Python
- Использование
- Строки в скрипте
- Загрузка и сохранение файла
- Текст в скрипте
- Авто-преобразование кодировки
- Результат
- Пример авто-преобразования кодировок в сравнении
- Результат
- Вывод списков
- Результат:
- Установка внешней кодировки при запуске
- Как я боролся с кодировками в консоли
- Как решить проблему с кодировкой UTF-8?
- encoding=’utf8′ не решает проблему с кодировкой при записи в файл
- 2 ответа 2
- Кодировки в python
- Общее
- Использование
Проблемы с кодировкой в Python
В python есть 2 объекта работающими с текстом: unicode и str, объект unicode хранит символы в формате (кодировке) unicode, объект str является набором байт/символов в которых python хранит остальные кодировки (utf8, cp1251, cp866, koi8-r и др).
Кодировку unicode можно считать рабочей кодировкой питона т.к. она предназначена для её использования в самом скрипте — для разных операций над строками.
Внешняя кодировка (объект str) предназначена для хранения и передачи текстовой информации вне скрипта, например для сохранения в файл или передачи по сети. Поэтому в данной статье я её назвал внешней. Самой используемой кодировкой в мире является utf8 и число приложений переходящих на эту кодировку растет каждый день, таким образом превращаясь в «стандарт».
Эта кодировка хороша тем что для хранения текста она занимает оптимальное кол-во памяти и с помощью её можно закодировать почти все языки мира ( в отличие от cp1251 и подобных однобайтовых кодировок). Поэтому рекомендуется везде использовать utf8, и при написании скриптов.
Использование
Скрипт питона, в самом начале скрипта указываем кодировку файла и сохраняем в ней файл
для того что-бы интерпретатор python понял в какой кодировке файл
Строки в скрипте
Строки в скрипте хранятся байтами, от кавычки до кавычки:
= 6 байт при cp1251
= 12 байт при utf8
Если перед строкой добавить символ u, то при запуске скрипта, эта байтовая строка будет декодирована в unicode из кодировки указанной в начале :
и если кодировка содержимого в файле отличается от указанной, то в строке могут быть «битые символы»
Загрузка и сохранение файла
Текст в скрипте
Процедуре print текст желательно передавать в рабочей кодировке либо кодировать в кодировку ОС.
Результат скрипта при запуске из консоли windows XP:
a2 = Текст в utf8
b = Текст в unicode
В последней строке print преобразовал unicode в cp866 автоматический, см. следующий пункт
Авто-преобразование кодировки
В некоторых случаях для упрощения разработки python делает преобразование кодировки, пример с методом print можно посмотреть в предыдущем пункте.
В примере ниже, python сам переводит utf8 в unicode — приводит к одной кодировке для того что-бы сложить строки.
Результат
a = Текст в utf8
b = Текст в unicode
c = Текст в utf8Текст в unicode
Как видим результирующая строка «c» в unicode. Если бы кодировки строк совпадали то авто-перекодирования не произошло бы и результирующая строка содержала кодировку слагаемых строк.
Авто-перекодирование обычно срабатывает когда происходит взаимодействие разных кодировок.
Пример авто-преобразования кодировок в сравнении
Результат
1. utf8 and unicode true
2. utf8 and cp1251 false
script.py:10: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode — interpreting them as being unequal
print ‘3. cp1251 and unicode’, ‘true’ if u’Слово’.encode(‘cp1251′) == u’Слово’ else ‘false’
3. cp1251 and unicode false
В сравнении 1, кодировка utf8 преобразовалась в unicode и сравнение произошло корректно.
В сравнении 2, сравниваются кодировки одного вида — обе внешние, т.к. кодированы они в разных кодировках условие выдало что они не равны.
В сравнении 3, выпало предупреждение из за того что выполняется сравнение кодировок разного вида — рабочая и внешняя, а авто-декодирование не произошло т.к. стандартная внешняя кодировка = utf8, и декодировать строку в кодировке cp1251 методом utf8 питон не смог.
Вывод списков
Результат:
1 [‘\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82’, ‘\xd1\x81\xd0\xbf\xd0\xb8\xd1\x81\xd0\xba\xd0\xb0’]
2 [‘\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82’, ‘\xd1\x81\xd0\xbf\xd0\xb8\xd1\x81\xd0\xba\xd0\xb0’]
При выводе списка, происходит вызов [
Установка внешней кодировки при запуске
В обучении ребенка важно правильное толкование окружающего его мира. Существует масса полезных журналов которые начнут экологическое воспитание дошкольников правильным путем. Развивать интерес к окружающему миру очень трудный но интересный процесс, уделите этому особое внимание.
Источник
Как я боролся с кодировками в консоли
В очередной раз запустив в Windows свой скрипт-информер для СамИздат-а и увидев в консоли «загадочные символы» я сказал себе: «Да уже сделай, наконец, себе нормальный кросс-платформенный логгинг!»
Об этом, и о том, как раскрасить вывод лога наподобие Django-вского в Win32 я попробую рассказать под хабра-катом (Всё ниженаписанное применимо к Python 2.x ветке)
Задача первая. Корректный вывод текста в консоль
Симптомы
До тех пор, пока мы не вносим каких-либо «поправок» в проинициализировавшуюся систему ввода-вывода и используем только оператор print с unicode строками, всё идёт более-менее нормально вне зависимости от ОС.
«Чудеса» начинаются дальше — если мы поменяли какие-либо кодировки (см. чуть дальше) или воспользовались модулем logging для вывода на экран. Вроде бы настроив ожидаемое поведение в Linux, в Windows получаешь «мусор» в utf-8. Начинаешь править под Win — вылезает 1251 в консоли…
Теоретический экскурс
Ищем решение
Очевидно, чтобы избавиться от всех этих проблем, надо как-то привести их к единообразию.
И вот тут начинается самое интересное:
Ага! Оказывается «система» у нас живёт вообще в ASCII. Как следствие — попытка по-простому работать с вводом/выводом заканчивается «любимым» исключением UnicodeEncodeError/UnicodeDecodeError .
Кроме того, как замечательно видно из примера, если в linux у нас везде utf-8, то в Windows — две разных кодировки — так называемая ANSI, она же cp1251, используемая для графической части и OEM, она же cp866, для вывода текста в консоли. OEM кодировка пришла к нам со времён DOS-а и, теоретически, может быть также перенастроена специальными командами, но на практике никто этого давно не делает.
До недавнего времени я пользовался распространённым способом исправить эту неприятность:
И это, в общем-то, работало. Работало до тех пор, пока пользовался print -ом. При переходе к выводу на экран через logging всё сломалось.
Угу, подумал я, раз «оно» использует кодировку по-умолчанию, — выставлю-ка я ту же кодировку, что в консоли:
Уже чуть лучше, но:
- В Win32 текст печатается кракозябрами, явно напоминающими cp1251
- При запуске с перенаправленным выводом опять получаем не то, что ожидалось
- Периодически, при попытке напечатать текст, где есть преобразованный в unicode символ типа ① ( ① ), «любезно» добавленный автором в какой-нибудь заголовок, снова получаем UnicodeEncodeError !
Присмотревшись к первому примеру, нетрудно заметить, что так желаемую кодировку «cp866» можно получить только проверив атрибут соответствующего потока. А он далеко не всегда оказывается доступен.
Вторая часть задачи — оставить системную кодировку в utf-8, но корректно настроить вывод в консоль.
Для индивидуальной настройки вывода надо переопределить обработку выходных потоков примерно так:
Этот код позволяет убить двух зайцев — выставить нужную кодировку и защититься от исключений при печати всяких умляутов и прочей типографики, отсутствующей в 255 символах cp866.
Осталось сделать этот код универсальным — откуда мне знать OEM кодировку на произвольном сферическом компе? Гугление на предмет готовой поддержки ANSI/OEM кодировок в python ничего разумного не дало, посему пришлось немного вспомнить WinAPI
… и собрать всё вместе:
Задача вторая. Раскрашиваем вывод
Насмотревшись на отладочный вывод Джанги в связке с werkzeug, захотелось чего-то подобного для себя. Гугление выдаёт несколько проектов разной степени проработки и удобности — от простейшего наследника logging.StreamHandler , до некоего набора, при импорте автоматически подменяющего стандартный StreamHandler.
Попробовав несколько из них, я, в итоге, воспользовался простейшим наследником StreamHandler, приведённом в одном из комментов на Stack Overflow и пока вполне доволен:
Однако, в Windows всё это работать, разумеется, отказалось. И если раньше можно было «включить» поддержку ansi-кодов в консоли добавлением «магического» ansi.dll из проекта symfony куда-то в недра системных папок винды, то, начиная (кажется) с Windows 7 данная возможность окончательно «выпилена» из системы. Да и заставлять юзера копировать какую-то dll в системную папку тоже как-то «не кошерно».
Снова обращаемся к гуглу и, снова, получаем несколько вариантов решения. Все варианты так или иначе сводятся к подмене вывода ANSI escape-последовательностей вызовом WinAPI для управления атрибутами консоли.
Побродив некоторое время по ссылкам, набрёл на проект colorama. Он как-то понравился мне больше остального. К плюсам именно этого проекта ст́оит отнести, что подменяется весь консольный вывод — можно выводить раскрашенный текст простым print u»\x1b[31;40mЧто-то красное на чёрном\x1b[0m» если вдруг захочется поизвращаться.
Сразу замечу, что текущая версия 0.1.18 содержит досадный баг, ломающий вывод unicode строк. Но простейшее решение я привёл там же при создании issue.
Собственно осталось объединить оба пожелания и начать пользоваться вместо традиционных «костылей»:
Дальше в своём проекте, в запускаемом файле пользуемся:
На этом всё. Из потенциальных доработок осталось проверить работоспособность под win64 python и, возможно, добаботать ColoredHandler чтобы проверял себя на isatty, как в более сложных примерах на том же StackOverflow.
Источник
Как решить проблему с кодировкой UTF-8?
Пишу в PyCharm и вроде как там с кодировкой проблем не должно возникать, однако удача меня обошла стороной.
При запуске локального сервера возникает следующая ошибка:
Unhandled exception in thread started by .wrapper at 0x035B1B28>
Traceback (most recent call last):
File «C:\Users\Tony\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\utils\autoreload.py», line 227, in wrapper
fn(*args, **kwargs)
File «C:\Users\Tony\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management\commands\runserver.py», line 149, in inner_run
ipv6=self.use_ipv6, threading=threading, server_cls=self.server_cls)
File «C:\Users\Tony\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\servers\basehttp.py», line 164, in run
httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
File «C:\Users\Tony\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\servers\basehttp.py», line 74, in __init__
super(WSGIServer, self).__init__(*args, **kwargs)
File «C:\Users\Tony\AppData\Local\Programs\Python\Python36-32\lib\socketserver.py», line 453, in __init__
self.server_bind()
File «C:\Users\Tony\AppData\Local\Programs\Python\Python36-32\lib\wsgiref\simple_server.py», line 50, in server_bind
HTTPServer.server_bind(self)
File «C:\Users\Tony\AppData\Local\Programs\Python\Python36-32\lib\http\server.py», line 138, in server_bind
self.server_name = socket.getfqdn(host)
File «C:\Users\Tony\AppData\Local\Programs\Python\Python36-32\lib\socket.py», line 673, in getfqdn
hostname, aliases, ipaddrs = gethostbyaddr(name)
UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xcf in position 5: invalid continuation byte
Заморочился и пересохранил все файлы в UTF-8 — не помогло. Пересмотрел кодировку каждого файла в самом PyCharm’e — везде UTF-8. Нашел на некоторых форумах такую же проблему — в качестве решения предлагалось переименовать имя компьютера в ASCII кодировку (на латинице короче говоря). Весь путь на латинице — ноль изменений. В каждом файле писал комментарий с кодировкой:
# coding: utf8
и вот так, что одно и то же
# -*- coding: utf-8 -*- .
Результата как не было, так и нет. Весь день копаюсь, так до сих пор и без понятия в чем дело.
Использую фреймворк Django (может что на нем завязано).
Надеюсь на вашу помощь. Заранее спасибо!
Источник
encoding=’utf8′ не решает проблему с кодировкой при записи в файл
UPD Если у вас такая же проблема и вы не хотите мучиться, то просто запишите файл в utf-16, а utf-8. У меня в задаче, кроме кириллицы и латиницы были ещё китайские и японские иероглифы, всё нормально записалось.
Я запарсил 200 страниц с данными 10к пользователей одного небольшого сайта и пытаюсь записать их в csv файл в таком формате:
И так 10 тысяч раз.
Всё идёт хорошо, пока дело не доходит до пользователей со всякими необычными символами в именах, выскакивает ошибка ‘charmap’ codec can’t encode character ‘\xf6′ in position 2: character maps to Я её загуглил и добавил encoding=’utf8’ в свой код, как советовали во всех ответах, ошибка исправилась, но все имена пользователей, в которых использовали кириллицу, записались вот так Крестьянин . Что делать? Может можно как-то разделить имена при парсинге или после него на нормальные и особенные? Вот функция записи в csv.
2 ответа 2
Проверьте users[‘Nickname’] , уверен уже в этих строках у вас будут кракозябры вида Крестьянин .
Если вы откуда-то скачиваете данные с этими строками убедитесь что она пришли как utf-8 и что вы с ними не делаете преобразования в cp1251 . Если у вас Windows, то преобразование в cp1251 может быть неявным при работе с методами encode / decode , или с bytes — если при работе с ними не указывать кодировку, то подставится системная.
Ниже информация по кодировкам (сложная эта тема. ).
Файл лучше всего хранить в кодировке utf-8 , но нужно убедиться, что и остальные строки у вас будут той же кодировке.
Например, берем исходную строку:
Как мы видим, в ней 10 символов. Теперь кодируем ее в байты как utf-8 :
И размер стал в два раза больше. Выходит, что кириллица в utf-8 хранится не в одном байте, а в двух. Теперь попробуем эту байтовую строку кодированную в utf-8 декодировать в строку cp1251 :
Получаем наши кракозябры. Это потому что cp1251 (она же windows-1251) однобайтовая кодировка.
Берем первые 4 байта из utf-8, декодируем как cp1251 и получаем знакомые символы:
Теперь мы зная причину появления кракозябр можем получить исходную строку через обратные действия:
Источник
Кодировки в python
прочтение статьи занимает 4мин, с обдумыванием — 10мин 🙂
примечание: данная статья относится к python 2.x, но для python 3.x принцип тот же
Общее
В python есть 2 объекта работающими с текстом: unicode и str, объект unicode хранит символы в формате (кодировке) unicode, объект str является набором байт/символов в которых python хранит остальные кодировки (utf8, cp1251, cp866, koi8-r и др).
Кодировку unicode можно считать рабочей кодировкой питона т.к. она предназначена для её использования в самом скрипте — для разных операций над строками.
Внешняя кодировка (объект str) предназначена для хранения и передачи текстовой информации вне скрипта, например для сохранения в файл или передачи по сети. Поэтому в данной статье я её назвал внешней. Самой используемой кодировкой в мире является utf8 и число приложений переходящих на эту кодировку растет каждый день, таким образом превращаясь в «стандарт». Эта кодировка хороша тем что для хранения текста она занимает оптимальное кол-во памяти и с помощью её можно закодировать почти все языки мира ( в отличие от cp1251 и подобных однобайтовых кодировок). Поэтому рекомендуется везде использовать utf8, и при написании скриптов.
Использование
для того что-бы интерпретатор python понял в какой кодировке файл
Строки в скрипте
Строки в скрипте хранятся байтами, от кавычки до кавычки:
= 6 байт при cp1251
= 12 байт при utf8
Если перед строкой добавить символ u, то при запуске скрипта, эта байтовая строка будет декодирована в unicode из кодировки указанной в начале:
и если кодировка содержимого в файле отличается от указанной, то в строке могут быть «битые символы»
Загрузка и сохранение файла
В последней строке print преобразовал unicode в cp866 автоматический, см. следующий пункт
Авто-преобразование кодировки
В некоторых случаях для упрощения разработки python делает преобразование кодировки, пример с методом print можно посмотреть в предыдущем пункте.
В примере ниже, python сам переводит utf8 в unicode — приводит к одной кодировке для того что-бы сложить строки.
Как видим результирующая строка «c» в unicode. Если бы кодировки строк совпадали то авто-перекодирования не произошло бы и результирующая строка содержала кодировку слагаемых строк.
Авто-перекодирование обычно срабатывает когда происходит взаимодействие разных кодировок.
Пример авто-преобразования кодировок в сравнении
В сравнении 1, кодировка utf8 преобразовалась в unicode и сравнение произошло корректно.
В сравнении 2, сравниваются кодировки одного вида — обе внешние, т.к. кодированы они в разных кодировках условие выдало что они не равны.
В сравнении 3, выпало предупреждение из за того что выполняется сравнение кодировок разного вида — рабочая и внешняя, а авто-декодирование не произошло т.к. стандартная внешняя кодировка = utf8, и декодировать строку в кодировке cp1251 методом utf8 питон не смог.
При выводе списка, происходит вызов [<repr>]() который возвращает внутреннее представление этого спиcка — print 1 и 2 являются аналогичными. Для корректного вывода списка, его нужно преобразовать в строку — print 3.
Установка внешней кодировки при запуске
статья будет дополняться.
Источник