Как я могу проверить строку Unicode Python, чтобы увидеть, что она * на самом деле * является правильным Unicode? - PullRequest
7 голосов
/ 15 августа 2010

Итак, у меня есть эта страница:

http://hub.iis.sinica.edu.tw/cytoHubba/

Очевидно, что все это запутано, так как оно правильно декодируется, но когда я пытаюсь сохранить его в postgres, я получаю:

DatabaseError: invalid byte sequence for encoding "UTF8": 0xedbdbf

После этого база данных замолкает и отказывается делать что-либо без отката, что будет довольно сложно выпустить (длинная история). Есть ли способ для меня, чтобы проверить, произойдет ли это, прежде чем он попадет в базу данных? source.encode ("utf-8") работает без проблем, поэтому я не уверен, что происходит ...

Ответы [ 5 ]

9 голосов
/ 18 августа 2010

Существует ошибка в python 2.x, которая является только исправленной python 3.x. На самом деле, эта ошибка есть даже в iconv OS X (но не в glibc).

Вот что происходит:

Python 2.x не распознает суррогатные пары UTF8 [1] как недопустимые (то есть последовательность символов)

Это должно быть всем, что нужно:

foo.decode('utf8').encode('utf8')

Но благодаря этой ошибке они не исправляются, она не ловит суррогатные пары.

Попробуйте это в python 2.x, а затем в 3.x:

b'\xed\xbd\xbf'.decode('utf8')

Это вызовет ошибку (правильно) в последнем. Они также не исправляют это в ветке 2.x. См. [2] и [3] для получения дополнительной информации

[1] http://tools.ietf.org/html/rfc3629#section-4

[2] http://bugs.python.org/issue9133

[3] http://bugs.python.org/issue8271#msg102209

1 голос
/ 15 августа 2010

Объект Python unicode - это последовательность кодовых точек Unicode и по определению собственно Unicode. Строка python str представляет собой последовательность байтов, которые могут быть символами Unicode, закодированными с определенной кодировкой (UTF-8, Latin-1, Big5, ...).

Первый вопрос возникает, если source это объект unicode или строка str. То, что source.encode("utf-8") работает, означает, что вы можете преобразовать source в строку в кодировке UTF-8, но делаете ли вы это перед тем, как передать ее в функцию базы данных? База данных, похоже, ожидает, что ее входные данные будут закодированы с помощью UTF-8, и жалуется, что эквивалент source.decode("utf-8") не срабатывает.

Если source является unicode объектом, он должен быть закодирован в UTF-8, прежде чем передать его в базу данных:

source = u'abc'
call_db(source.encode('utf-8'))

Если source - это str, закодированный как-то иначе, чем Utf-8, вы должны декодировать это кодирование и затем кодировать полученный объект Unicode в UTF-8:

source = 'abc'
call_db(source.decode('Big5').encode('utf-8'))
0 голосов
/ 07 августа 2012

Чтобы решить мои подобные проблемы с django / postgress, я сейчас делаю что-то вроде этого

class SafeTextField(models.TextField)
    def get_prep_value(self, value):
        encoded = base64.encodestring(value).strip()
        return super(SafeTextField, self).get_prep_value(encoded)
    def to_python(self, value):
        decoded = base64.decodestring(value)
        return super(SafeTextField, self).to_python(decoded)
0 голосов
/ 15 августа 2010

В итоге я решил просто обойти это, отловить ошибку и откатить транзакцию, используя управление транзакциями в Django.Я озадачен тем, почему это произошло, хотя ...

0 голосов
/ 15 августа 2010

Что именно вы делаете? Контент действительно хорошо декодируется как utf-8:

>>> import urllib
>>> webcontent = urllib.urlopen("http://hub.iis.sinica.edu.tw/cytoHubba/").read()
>>> unicodecontent = webcontent.decode("utf-8")
>>> type(webcontent)
<type 'str'>
>>> type(unicodecontent)
<type 'unicode'>
>>> type(unicodecontent.encode("utf-8"))
<type 'str'>

Убедитесь, что вы понимаете разницу между строками Unicode и строками в кодировке utf-8. Вам нужно отправить в базу данных unicodecontent.encode("utf-8") (то же самое, что и webcontent, но вы расшифровали, чтобы убедиться, что у нет неверных последовательностей байтов в вашем источнике).

Я бы, как сказал WoLpH, проверил настройки базы данных и соединения с базой данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...