Python + PostgreSQL + странная ascii = ошибка кодировки UTF8 - PullRequest
6 голосов
/ 07 июня 2010

У меня есть строки ascii, которые содержат символ "\x80" для обозначения символа евро:

>>> print "\x80"
€

При вставке строковых данных, содержащих этот символ, в мою базу данных, я получаю:

psycopg2.DataError: invalid byte sequence for encoding "UTF8": 0x80
HINT:  This error can also happen if the byte sequence does not match the encodi
ng expected by the server, which is controlled by "client_encoding".

Я новичок в юникоде. Как я могу преобразовать мои строки, содержащие "\x80", в действительный UTF-8, содержащий тот же символ евро? Я пытался вызвать .encode и .decode для разных строк, но столкнулся с ошибками:

>>> "\x80".encode("utf-8")
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    "\x80".encode("utf-8")
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)

1 Ответ

12 голосов
/ 08 июня 2010

Вопрос начинается с ложной предпосылки:

У меня есть строки ascii, которые содержат символ "\ x80" для обозначения символа евро.

Символы ASCII находятся в диапазоне от \ x00 до \ x7F включительно.

Ранее принятый, теперь удаленный ответ действовал в двух грубых заблуждениях (1) в этой локали == encoding (2), когда кодировка latin1 отображает "\ x80" в символ евро.

Фактически, все кодировки ISO-8859-x соответствуют "\ x80" U + 0080, который является одним из управляющих символов C1, а не символом евро. Только 3 из этих кодировок (x в (7, 15, 16)) предоставляют символ евро, как "\ xA4". См. эту статью в Википедии .

Вам необходимо знать в какой кодировке находятся ваши данные. На каком компьютере они были созданы? Как? Язык, в котором он был создан (не обязательно ваш), может дать вам подсказку.

Обратите внимание, что "Мои данные закодированы в латинице 1" там с "Чек в почте" и "Конечно, я буду любить тебя утром". Ваши данные, вероятно, закодированы в одной из кодировок cp125x на платформах Windows. Обратите внимание, что все они, за исключением кириллицы cp1251 (Windows кириллицы), сопоставляют символ "\ x80" с символом евро:

>>> ['\x80'.decode('cp125' + str(x), 'replace') for x in range(9)]
[u'\u20ac', u'\u0402', u'\u20ac', u'\u20ac', u'\u20ac', u'\u20ac', u'\u20ac', u'\u20ac', u'\u20ac']

Обновление в ответ на комментарий ОП

Я читаю эти данные из файла, например, open(fname).read(). Он содержит строки с \ x80 в них, который представляет символ евро. это просто текстовый файл. он генерируется другой программой, но я не знаю, как это происходит с генерацией текста. что было бы хорошим решением? Я думаю, я могу предположить, что он выводит «\ x80» для символа евро, то есть я могу предположить, что он закодирован с cp125x, который имеет этот символ в виде евро.

Это немного сбивает с толку: сначала вы говорите

Содержит строки с \ x80 в них, который представляет символ евро

Но позже вы говорите

Я думаю, что могу предположить, что он выводит "\ x80" для символа евро

Пожалуйста, объясните.

Выбор подходящей кодировки cp125x: Где (географическое положение) был создан файл? На каком языке написан текст? Любые символы, кроме предполагаемого евро со значениями> "\ x7f"? Если да, то в каких и в каком контексте они используются?

Обновление 2 Если вы «не знаете, как написана программа», ни вы, ни мы не можем составить мнение о том, всегда ли она использует «\ x80» для символа евро. Хотя поступить иначе было бы монументальной глупостью, это нельзя исключать.

Если текст написан на английском языке и / или написан в США, и / или написан на платформе Windows, то вполне вероятно, что cp1252 - это путь ... пока вы получите доказательства обратного, и в этом случае вам нужно будет угадать кодировку самостоятельно или ответить на вопросы (на каком языке, в каком месте).

...