Python - проблема, хранящая символ Unicode к MySQL с Django

Я принял бы (с @eed3s9n), что он должен способствовать слабой связи. Кроме того, без интерфейсов поблочное тестирование становится намного более трудным, поскольку Вы не можете копировать свои объекты.

7
задан Taryn 17 November 2013 в 14:22
поделиться

7 ответов

Thank you to everyone who was posting here. It really helps my unicode knowledge (and hoepfully other people learned something).

We seemed to be all barking up the wrong tree since I tried to simplify my problem and didn't give ALL information. It seems that I wasn't using "REAL" unicode strings, but rather BeautifulSoup.NavigableString which repr themselves as unicode strings. So all the printouts looked like unicode, but they weren't.

Somewhere deep in the MySQLDB library they couldn't deal with these strings.

This worked :

>>> Achievement.objects.get(name = u"Mirror's Edge\u2122")
<Achievement: Mirror's Edge™>

On the other hand :

>>> b = BeautifulSoup(u"<span>Mirror's Edge\u2122</span>").span.string
>>> Achievement.objects.get(name = b)
... Exceptoins ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 13: ordinal not in range(128)

But this works :

>>> Achievement.objects.get(name = unicode(b))
<Achievement: Mirror's Edge™>

So, thanks again for all the unicode help, I'm sure it will come in handy. But for now ...

WARNING : BeautifulSoup doesn't return REAL unicode strings and should be coerced with unicode() before doing anything meaningful with them.

12
ответ дан 6 December 2019 в 10:02
поделиться

Вы используете строки типа unicode. Если ваша модель или серверная часть SQL не поддерживает их или не знает, как преобразовать в UTF-8, просто выполните преобразование самостоятельно. Придерживайтесь простых строк (тип python str) и конвертируйте, как в

a = models.Achievement(name=u"Played Mirror's Edge\u2122".encode("UTF-8"))
3
ответ дан 6 December 2019 в 10:02
поделиться

Я согласен с Николаем. Я уже столкнулся с проблемой использования UTF-8 даже в чистом Python (2.5).

Наконец, я использовал функцию Unicode (?):

entry    = unicode(sys.stdin, ENCODING)

КОДИРОВАНИЕ зависело от локали, если я хорошо помню:

import sys, locale

ENCODING    = locale.getdefaultlocale()[1]
DEFAULT_ENCODING    = sys.getdefaultencoding()

Может быть взгляните на Python Unicode HOWTO ?

0
ответ дан 6 December 2019 в 10:02
поделиться

Я работал над этим вчера и обнаружил, что добавление "charset = utf8" и "use_unicode = 1" в строку подключения заставило его работать (используя SQLAlchemy, думаю, это та же проблема) .

Итак, моя строка выглядит так: "mysql: // user: pass @ host : 3306 / database? use_unicode = 1 & charset = utf8"

1
ответ дан 6 December 2019 в 10:02
поделиться

Для меня апостроф выглядит странно, если его не экранировать следующим образом:

u"Played Mirror\'s Edge\u2122"
-1
ответ дан 6 December 2019 в 10:02
поделиться

Несколько замечаний:

  • Python 2.x имеет два строковых типа

    • "str", которые в основном представляют собой массив байтов (так что вы можете хранить в нем все, что захотите)
    • «Юникод», который является внутренне закодированным Юникодом UCS2 / UCS4
  • Экземпляры этих типов считаются «декодированными» данными. Внутреннее представление - это ссылка, поэтому вы «декодируете» в него внешние данные и «кодируете» в некоторый внешний формат.

  • Хорошая стратегия - декодировать как можно раньше, когда данные поступают в систему, и кодировать как можно позже возможное. Постарайтесь как можно больше использовать Unicode для строк в вашей системе. (Я не согласен с Николаем в этом отношении.)

  • Этот аспект кодирования применим к ответу Николая. Он берет исходную строку Unicode и кодирует ее в utf-8. Но это не t решить проблему (по крайней мере, в общем случае), потому что результирующий байтовый буфер может по-прежнему содержать байты вне диапазона (127) (я не проверял наличие \ u2122), что означает, что вы будете снова попадет в то же исключение.

  • Тем не менее, анализ Николая показывает, что вы передаете строку Unicode, но где-то в системе это считается экземпляром str. Достаточно, если где-то к вашему аргументу unicode применяется функция str ().

  • В этом случае Python использует так называемую кодировку по умолчанию, которая является ascii, если вы не измените ее. Существует функция sys.setdefaultencoding, которую вы можете использовать для переключения, например, на utf-8, но эта функция доступна только в ограниченном контексте, поэтому вы не можете легко использовать ее в коде приложения.

  • Я чувствую, что проблема где-то глубже в слои, которые вы вызываете. К сожалению, Я не могу комментировать Django или MySQL / SQLalchemy, но мне интересно, можете ли вы указать тип Unicode при объявлении атрибута name в вашей модели. Было бы хорошей практикой БД обрабатывать информацию о типе на уровне поля. Может быть, есть альтернатива CharField?!

  • И да, вы можете безопасно вставить одинарную кавычку (') в строку с двойными кавычками ("), и наоборот.

4
ответ дан 6 December 2019 в 10:02
поделиться

У меня были похожие проблемы с mysql и postgres, но не было проблем с sqllite.

Вот как я решил проблему с postgres (не тестировал этот трюк с mysql, но я предполагаю, что он решит это тоже)

в файле, где u работает со строкой Unicode, выполните

from django.utils.safestring import SafeUnicode

и предположите, что unistr - это переменная, содержащая строку, выполните

unistr = SafeUnicode(unistr)

в моем случае, я скребл с веб-сайта

исходный код, который вызывал проблемы (ht - объект beautifulsoup): -

keyword = ht.a.string

исправление: -

keyword = SafeUnicode(ht.a.string)

Я не знаю, почему и что делает SafeUnicode, все, что я знаю, это решило мои проблемы.

0
ответ дан 6 December 2019 в 10:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: