Unicodeencodeerror python как исправить

This code should write some text to file.
When I’m trying to write my text to console, everything works. But when I try to write the text into the file, I get UnicodeEncodeError. I know, that this is a common problem which can be solved using proper decode or encode, but I tried it and still getting the same UnicodeEncodeError. What am I doing wrong?

I’ve attached an example.

print "(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)".decode("utf-8")%(dict.get('name'),dict.get('description'),dict.get('ico'),dict.get('city'),dict.get('ulCislo'),dict.get('psc'),dict.get('weby'),dict.get('telefony'),dict.get('mobily'),dict.get('faxy'),dict.get('emaily'),dict.get('dic'),dict.get('ic_dph'),dict.get('kategorie')[0],dict.get('kategorie')[1],dict.get('kategorie')[2])

(StarBuy s.r.o.,Inzertujte s foto, auto-moto, oblečenie, reality, prácu, zvieratá, starožitnosti, dovolenky, nábytok, všetko pre deti, obuv, stroj….

with open("test.txt","wb") as f:
   f.write("(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)".decode("utf-8")%(dict.get('name'),dict.get('description'),dict.get('ico'),dict.get('city'),dict.get('ulCislo'),dict.get('psc'),dict.get('weby'),dict.get('telefony'),dict.get('mobily'),dict.get('faxy'),dict.get('emaily'),dict.get('dic'),dict.get('ic_dph'),dict.get('kategorie')[0],dict.get('kategorie')[1],dict.get('kategorie')[2]))

UnicodeEncodeError: ‘ascii’ codec can’t encode character u’u010d’ in position 50: ordinal not in range(128)

Where could be the problem?

9 декабря, 2022 12:22 пп
1 569 views
| Комментариев нет

Development, Python

Unicode (Юникод)  — это стандарт кодирования символов для большинства компьютеров. Он гарантирует, что текст — включая буквы, символы, эмодзи и даже управляющие символы — будет выглядеть одинаково на разных устройствах, платформах и в цифровых документах, независимо от операционной системы или программного обеспечения. Это важная составляющая интернета и компьютерной индустрии в целом. Без него всё было бы сложно и хаотично.

Unicode сам по себе не является кодировкой, а больше похож на базу данных почти всех возможных символов. В нём есть кодовая точка (идентификатор для каждого символа в базе данных), которая может иметь значение от 0 до 1,1 миллиона – как видите, скорее всего в ближайшее время эти уникальные кодовые точки не закончатся. Каждая кодовая точка в Unicode обозначается U+n, где U+ — кодовая точка Unicode, а n — это набор для символа из четырех-шести шестнадцатеричных цифр. Unicode намного надежнее ASCII, в котором только 128 символов. Обмен цифровым текстом с помощью ASCII сложнее, так как он основан на американском английском и не поддерживает символы с диакритическими знаками. А в Unicode почти 150 000 символов и он охватывает символы всех языков мира.

Поэтому от языков программирования и требуется правильно обрабатывать текст и обеспечивать интернационализацию программного обеспечения. Python используют для разных целей — от электронной почты до серверов и интернета —  у него отличный способ обработки Unicode, он принимает стандарт Unicode для своих строк.

Иногда в работе с Unicode в Python могут возникать трудности и ошибки. В этом мануале представлены основы работы Unicode в Python, которые помогут вам избежать этих проблем. С помощью Python мы интерпретируем Unicode, применим к Unicode функцию нормализации и обработаем ошибки.

Требования

Нам понадобится:

  • Python, установленный локально или на удаленном сервере. Если у вас еще не установлен Python, ознакомьтесь с этим мануалом.
  • Знание основ программирования и строковых методов Python. Читайте Основы работы со строками в Python 3.
  • Знание принципов работы с интерактивной консолью Python. Читайте мануал Использование интерактивной консоли Python.

1: Конвертирование кодовых точек Unicode в Python

Кодирование — это процесс представления данных в читаемой компьютером форме. Существуют разные способы кодирования данных — ASCII, Latin-1 и т. д. У каждой кодировки свои сильные и слабые стороны, но пожалуй, самой распространенной является UTF-8 —  тип кодирования, который отображает символы со всего мира в одном наборе. То есть, UTF-8 это незаменимый инструмент для всех, кто работает с интернационализированными данными. В целом, UTF-8 справляется с многими задачами. Он относительно эффективен и может работать в разных программах. UTF-8 конвертирует кодовую точку Unicode в понятные компьютеру шестнадцатеричные байты. Другими словами, Unicode – это маппинг, а UTF-8 позволяет компьютеру понять этот маппинг.

В Python 3 кодировка строк по умолчанию – UTF-8, значит, любая кодовая точка Unicode в строке Python автоматически конвертируется в соответствующий символ.

Сейчас мы создадим символ авторского права (©) с помощью его кодовой точки Unicode в Python. Сначала запустите интерактивную консоль Python в терминале, а затем введите:

>>> s =  'u00A9'
>>> s

В этом коде мы создали строку s с кодовой точкой Unicode u00A9. Как упоминалось ранее, поскольку строка Python по умолчанию использует кодировку UTF-8, вывод значения s автоматически заменяет его на соответствующий символ Unicode. Обратите внимание, что u в начале кода обязателен. Без него Python не сможет конвертировать кодовую точку. В выводе получим соответствующий символ Unicode:

'©'

В Python есть встроенные функции для кодирования и декодирования строк. Функция encode() конвертирует строку в байтовую строку.

Для этого откройте интерактивную консоль Python и введите код:

>>> ''.encode('utf-8')

В результате получим байтовую строку символа:

b'xf0x9fx85xa5'

Обратите внимание, что перед каждым байтом стоит x, значит, это шестнадцатеричное число.

Примечание: Ввод спецсимволов Unicode в Windows и Mac отличается. В Windows предыдущий и все последующие примеры этого мануала, где используются символы, вы можете вставить с помощью утилиты Character Map. В Mac нет этой функции, поэтому лучше скопировать символ из примера кода.

Далее с помощью функции decode() конвертируем байтовую строку в обычную. Функция decode() принимает в качестве аргумента тип кодировки. Отметим, что функция decode() может декодировать только байтовую строку, которая задается с помощью буквы b в начале строки. Удаление b приведет к ошибке AttributeError.

В консоли введите:

>>> b'xf0x9fx85xa5'.decode('utf-8')

Получим следующий вывод:

''

Теперь у вас есть базовое понимание интерпретации Unicode в Python. Далее мы разберем встроенный в Python модуль unicodedata, чтобы применить расширенные методы Unicode для строк.

2: Нормализация Unicode в Python

С помощью нормализации можно определить, одинаковы ли два символа, написанные разными шрифтами. Это удобно, когда два символа с разными кодовыми точками дают одинаковый результат. Например, мы воспринимаем символы Unicode R и ℜ как одинаковые, поскольку они оба представляют собой букву R, но для компьютера они разные.

Следующий пример кода это демонстрирует. Откройте консоль Python и введите следующее:

>>> styled_R = 'ℜ'
>>> normal_R = 'R'
>>> styled_R == normal_R

В результате получим:

False

Вывод будет False, потому что Python не считает эти два символа одинаковыми. Именно поэтому нормализация важна при работе с Unicode.

В Unicode некоторые символы создаются путем объединения нескольких символов в один. Нормализация также важна в этом случае, потому что она обеспечивает согласованность строк. Рассмотрим это на примере. Откройте консоль Python и введите код:

>>> s1 =  'hôtel'
>>> s2 = 'hou0302tel'
>>> len(s1), len(s2)

В этом коде мы создали строку s1, содержащую символ ô, а строка s2 содержит кодовую точку символа циркумфлекса ( ̂ ). Получим такой вывод:

(5, 6)

Это значит, что две строки состоят из одинаковых символов, но имеют разную длину. Значит, они не подходят под условие равенства. Чтобы это проверить, введите в той же консоли:

>>> s1 == s2

Получим вывод:

False

Хотя строковые переменные s1 и s2 производят один и тот же символ Unicode, они различаются по длине и, следовательно, не равны.

Решить эту проблему можно с помощью функции normalize().

3: Нормализация Unicode с помощью NFD, NFC, NFKD и NFKC

Сейчас мы нормализуем строки Unicode с помощью функции normalize() из библиотеки unicodedata Python в модуле unicodedata (он обеспечивает поиск и нормализацию символов). Функция normalize() может принимать форму нормализации в качестве первого аргумента и нормализуемую строку в качестве второго аргумента. В Unicode существует четыре типа форм нормализации: NFD, NFC, NFKD и NFKC.

NFD разбивает символ на несколько комбинируемых символов. Это делает текст нечувствительным к диакритическим символам, что удобно при поиске и сортировке. Для этого нужно закодировать строку в байты.

Откройте консоль и введите следующее:

>>> from unicodedata import normalize
>>> s1 =  'hôtel'
>>> s2 = 'hou0302tel'
>>> s1_nfd = normalize('NFD', s1)
>>> len(s1), len(s1_nfd)

Получим следующий вывод:

(5, 6)

При нормализации строки s1 ее длина увеличилась на один символ. Это происходит по причине того, что символ ô разбивается на два символа — o и ˆ. Следующий код это подтвердит:

>>> s1.encode(), s1_nfd.encode()

В результате, после кодирования нормализованной строки символ o отделился от символа ˆ в строке s1_nfd:

(b'hxc3xb4tel', b'hoxccx82tel')

Форма нормализации NFC раскладывает символ, а затем перекомпонует его с любым доступным объединяющим символом. W3C рекомендует использовать NFC в интернете, поскольку NFC компонует строку для получения максимально короткого результата. Ввод с клавиатуры по умолчанию возвращает составленные строки, поэтому в этом случае рекомендуется применять NFC.

Для примера введите в интерактивную консоль:

>>> from unicodedata import normalize
>>> s2_nfc = normalize('NFC', s2)
>>> len(s2), len(s2_nfc)

Вывод будет следующим:

(6, 5)

При нормализации строки s2 её длина уменьшилась на единицу. Введите код в интерактивной консоли:

>>> s2.encode(), s2_nfc.encode()

Вывод будет таким:

(b'hoxccx82tel', b'hxc3xb4tel')

Символы o и ˆ соединены в один символ ô.

Формы нормализации NFKD и NFKC применяют для «строгой» нормализации и поиска, сопоставления  образцов в строках Unicode. “K” в NFKD и NFKC означает совместимость.

NFD и NFC разделяют символы, но NFKD и NFKC выполняют разделение на совместимость для непохожих эквивалентых символов, при этом удаляются любые различия форматирования. Например, строка ②① не похожа на 21, но обе имеют одно значение. Формы нормализации NFKC и NFKD удаляют форматирование (в данном случае круг вокруг цифр) из символов, чтобы представить их упрощенную форму.

На примере разберем разницу между NFD и NFKD. Откройте интерактивную консоль Python и введите:

>>> s1 = '2⁵ô'
>>> from unicodedata import normalize
>>> normalize('NFD', s1), normalize('NFKD', s1)

Получаем следующий вывод:

('2⁵ô', '25ô')

Форма NFD не смогла разделить символ экспоненты в строке s1, но NFKD вырезала форматирование экспоненты и заменила символ совместимости (в данном случае экспоненту 5) на его эквивалент (5 в виде цифры). Так как NFD и NFKD разделяют символы, следовательно, ô увеличит длину на единицу. Это подтвердит следующее:

>>> len(normalize('NFD', s1)), len(normalize('NFKD', s1))

Код возвращает:

(4, 4)

Принцип работы NFKC аналогичный, но он скорее не разделяет символы, а компонует их. В консоли Python введите:

>>> normalize('NFC', s1), normalize('NFKC', s1)

Вывод будет следующим:

('2⁵ô', '25ô')

Строка для символа ô уменьшится на единицу, поскольку в NFKC композиционный подход (в случае разделения значение увеличивается на единицу). Проверим это с помощью кода:

>>> len(normalize('NFC', s1)), len(normalize('NFKC', s1))

Получаем вывод:

(3, 3)

Мы разобрали типы нормализации и различия между ними. Далее мы устраним ошибки Unicode в Python.

4: Устранение ошибок Unicode в Python

При работе с Unicode в Python могут возникать два типа ошибок: UnicodeEncodeError и UnicodeDecodeError. Теперь разберем пути их устранения.

Устранение ошибки UnicodeEncodeError

Кодирование в Unicode — это процесс конвертирования строки Unicode в байты с помощью определенной кодировки. Ошибка UnicodeEncodeError возникает при попытке закодировать строку, символы которой не могут быть представлены в заданной кодировке.

Чтобы создать эту ошибку, давайте попробуем закодировать строку с символами, которые не входят в набор ASCII.

Откройте консоль и введите:

>>> ascii_supported = 'u0041'
>>> ascii_supported.encode('ascii')

Вывод будет:

b'A'

Затем введите:

>>> ascii_unsupported = 'ufb06'
>>> ascii_unsupported.encode('utf-8')

Получим следующий результат:

b'xefxacx86'

Наконец, введите следующее:

>>> ascii_unsupported.encode('ascii')

При запуске этого кода возникнет ошибка:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>

UnicodeEncodeError: ‘ascii’ codec can’t encode character ‘ufb06’ in position 0: ordinal not in range(128)

В ASCII ограниченное количество символов, поэтому Python выдает ошибки при нахождении символа, которого нет в кодировке ASCII. Поскольку кодовая система ASCII не распознает кодовую точку ufb06, Python выдаст сообщение об ошибке. В нем идет речь о том, что ASCII имеет диапазон только 128 символов, а соответствующий десятичный эквивалент этой кодовой точки не входит в этот диапазон.

UnicodeEncodeError можно обработать с помощью аргумента errors в функции encode(). У аргумента errors может быть одно из трех значений: ignore, replace и xmlcharrefreplace.

Откройте консоль и введите:

>>> ascii_unsupported = 'ufb06'
>>> ascii_unsupported.encode('ascii', errors='ignore')

Получим следующий вывод:

b''

Далее введите:

>>> >>> ascii_unsupported.encode('ascii', errors='replace')

Вывод будет таким:

b'?'

Наконец, введите:

>>> ascii_unsupported.encode('ascii', errors='xmlcharrefreplace')

В результате получим:

b'st'

Во всех случаях Python не выдает ошибку. Значение

ignore пропускает символ, который не может быть закодирован; replace заменяет символ знаком ?; а xmlcharrefreplace заменяет некодируемые символы сущностью XML.

Устранение ошибки UnicodeDecodeError

Ошибка UnicodeEncodeError возникает при попытке декодировать строку, символы которой не могут быть представлены в заданной кодировке.

Чтобы создать эту ошибку, мы попробуем декодировать строку байтов в кодировку, которую невозможно декодировать.

Откройте консоль и введите:

>>> iso_supported = '§'
>>> b = iso_supported.encode('iso8859_1')
>>> b.decode('utf-8')

Получим следующую ошибку:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa7 in position 0: invalid start byte

Если вы столкнулись с этой ошибкой, можете применить аргумент errors в функции decode(), c помощью которого можно декодировать строку. Аргумент errors принимает два значения: ignore и replace.

Откройте консоль Python и введите код:

>>> iso_supported = '§A'
>>> b = iso_supported.encode('iso8859_1')
>>> b.decode('utf-8', errors='replace')

Вывод будет следующим:

'�A'

Затем введите:

>>> b.decode('utf-8', errors='ignore')

Получим такой вывод:

'A'

Значение replace в функции decode() добавляет символ �, а ignore ничего не возвращает, поскольку декодер (в данном случае utf-8) не смог декодировать байты.

При декодировании строки следует помнить, что предполагать ее кодировку нельзя, нужно точно знать, как именно она была закодирована.

Подводим итоги

В этом мануале мы рассмотрели основы работы Unicode в Python. Мы кодировали и декодировали строки, нормализовали данные с помощью NFD, NFC, NFKD и NFKC, а также устранили ошибки Unicode. Также мы применили формы нормализации в сценариях сортировки и поиска. Эти методы помогут устранить ошибки Unicode с помощью Python. Рекомендуем ознакомиться с материалами модуля unicodedata.

Tags: Python, Unicode

 debian, python, unicode


0

2

Traceback (most recent call last): File "betfair.py", line 10, in <module>   print('u041fu0410u0420u0421u0418u0422u0421u042f ' + baseurl + parturl) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128)

Строка такая:

print('ПАРСИТСЯ ' + baseurl + parturl)

Почему так и как исправить?

На убунте 14.04 работает

  • Ссылка

Ответ на:

комментарий
от yars068 12.05.16 11:18:17 MSK

Сделал

msg = 'ПАРСИТСЯ ' + baseurl + parturl
msg = msg.encode('utf-8')
print(msg)

Теперь мне выводит в виде кодов юникода, а надо по-русски( Я с мобилки – все не очень удобно делать(
Что я делаю не так и почему на убунте работает?

Qwentor ★★★★★

(12.05.16 12:07:11 MSK)

  • Показать ответ
  • Ссылка

Ответ на:

комментарий
от Qwentor 12.05.16 12:07:11 MSK

Ответ на:

комментарий
от bvn13 12.05.16 15:33:20 MSK

Ответ на:

комментарий
от Qwentor 12.05.16 15:49:11 MSK

Ну так поставь себе юникодную локаль. sudo dpkg-reconfigure locales, и там нужные настройки.

  • Показать ответ
  • Ссылка

Ответ на:

комментарий
от proud_anon 12.05.16 16:05:48 MSK

Недавно наткнулся на такое. Решение — либо костылять свой print через sys.stdout.buffer, либо поправить локаль в переменной окружения на UTF-8. Например LC_ALL='ru_RU.UTF-8',LANG='ru_RU.UTF-8'.

PolarFox ★★★★★

(12.05.16 16:38:37 MSK)

  • Ссылка

Ответ на:

комментарий
от Qwentor 12.05.16 16:33:51 MSK

ru_RU.UTF-8

Не обязательно. Любая юникодная сойдёт. Или любая с русскими символами.

PolarFox ★★★★★

(12.05.16 16:39:31 MSK)

  • Ссылка

Ответ на:

комментарий
от Qwentor 12.05.16 16:33:51 MSK

Мне нужно установить ru_RU.UTF-8 по-умолчанию? Установил как вторую – без толку

Любую .UTF-8. Если ты почему-то не хочешь устанавливать UTF-8-локаль по умолчанию, то запускай скрипт как LANG=ru_RU.UTF betfair.py (или любую другую UTF-8-локаль).

  • Показать ответ
  • Ссылка

Ответ на:

комментарий
от proud_anon 12.05.16 16:44:50 MSK

Йоу, спасибище! Помогло!
Нажал бы плюсик, если б было)

Qwentor ★★★★★

(12.05.16 17:13:07 MSK)

  • Ссылка

Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.

Похожие темы

  • Форум
    Снова юникод в python (2012)
  • Форум
    Питон, юникод и конвеер (2015)
  • Форум
    Python: как принудить к utf-8? (2009)
  • Форум
    [conky][utf-8][python] Не работает вывод в conky (2010)
  • Форум
    python && utf-8 (2005)
  • Форум
    [python][unicode]jinja (2008)
  • Форум
    Python, Informix и more (2008)
  • Форум
    [python3.2][archlinux] (2011)
  • Форум
    Playonlinux не ищет ничего (2014)
  • Форум
    lubuntu-software-center crash (2013)

The UnicodeEncodeError normally happens when encoding a unicode string into a certain coding. Since codings map only a limited number of unicode characters to str strings, a non-presented character will cause the coding-specific encode() to fail.

Encoding from unicode to str.

>>> u"a".encode("iso-8859-15")
'a'
>>> u"u0411".encode("iso-8859-15")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "encodings/iso8859_15.py", line 12, in encode
UnicodeEncodeError: 'charmap' codec can't encode character u'u0411' in position 0: character maps to <undefined>

>>> u"au0411b".encode("iso-8859-15", "replace")
'a?b'
>>> u"au0411b".encode("iso-8859-15", "backslashreplace")
'a\u0411b'
>>> u"au0411b".encode("iso-8859-15", "xmlcharrefreplace")
'aБb'

Paradoxically, a UnicodeEncodeError may happen when _decoding_. The cause of it seems to be the coding-specific decode() functions that normally expect a parameter of type str. It appears that on seeing a unicode parameter, the decode() functions “down-convert” it into str, then decode the result assuming it to be of their own coding. It also appears that the “down-conversion” is performed using the ASCII encoder. Hence an encoding failure inside a decoder.

The choice of the ASCII encoder for “down-conversion” might be considered wise because it is an intersection of all codings. The subsequent decoding may only accept a coding-specific str.

However, unlike a similar issue with UnicodeDecodeError while encoding, there would be not ambiguity if decode() simply returned the unicode argument unmodified. There seems to be not such a shortcut in decode() functions as of Python2.5.

Alternatively, a TypeError exception could always be thrown on receiving a unicode argument in decode() functions. (This would require stream.read() to produce only str for StreamReader.read(). The latter would only produce unicode).

Decoding from str to unicode.

>>> "a".decode("utf-8")
u'a'
>>> "xd0x91".decode("utf-8")
u'u0411'
>>> u"a".decode("utf-8")      # Unexpected argument type.
u'a'
>>> u"u0411".decode("utf-8") # Unexpected argument type.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "encodings/utf_8.py", line 16, in decode
UnicodeEncodeError: 'ascii' codec can't encode character u'u0411' in position 0: ordinal not in range(128)

Python 3000 will prohibit decoding of Unicode strings, according to PEP 3137: “encoding always takes a Unicode string and returns a bytes sequence, and decoding always takes a bytes sequence and returns a Unicode string”.


CategoryUnicode

so i’m trying to scrap data about motherboard from a local website.

import bs4
import os
import requests

from bs4 import BeautifulSoup as soup

os.chdir('E://')
os.makedirs('E://scrappy', exist_ok=True)
myurl = "https://www.example.com"
res = requests.get(myurl)
page = soup(res.content, 'html.parser')
containers = page.findAll("div", {"class": "content-product"})
filename = 'AM4.csv'
f = open(filename, 'w')
headers = 'Motherboard_Name, Pricen'
f.write(headers)

for container in containers:
    Product = container.findAll("div", {"class": "product-title"})
    Motherboard_Name = Product[0].text.strip()
    Kimat = container.findAll("span", {"class": "price"})
    Price = Kimat[0].text
    print('Motherboard_Name' + Motherboard_Name)
    print('Price' + Price)
    f.write(Motherboard_Name + "," + Price.replace(",", "") + "n")
f.close() print("done")

But when i run this code i get an error

UnicodeEncodeError:’charmap’ codec can’t encode character ‘u20b9’ in position 45: character maps to

how can i fix this??

Edit:: So i fixed the unicode error by adding encoding=”utf-8″ ( as it was mentioned here python 3.2 UnicodeEncodeError: ‘charmap’ codec can’t encode character ‘u2013’ in position 9629: character maps to <undefined>) (open(filename, ‘w’,encoding=”utf-8″ ))and it seems to do the work however in the csv file m getting characters like ( ₹ ) before the price.. How can i fix this?

screenshot of the csv file

Добавить комментарий