python – Проблема сохранения символа Unicode для MySQL с Django

У меня есть строка

u"Played Mirror's Edge\u2122" 

Который должен быть показан как

  Played Mirror's Edge™ 

Но это еще одна проблема. Моя проблема в том, что я помещаю ее в модель, а затем пытаюсь сохранить ее в базе данных. AKA:

 a = models.Achievement(name=u"Played Mirror's Edge\u2122") a.save() 

И я получаю:

 'ascii' codec can't encode character u'\u2122' in position 13: ordinal not in range(128) 

полная трассировка стека (по запросу):

 Traceback: File "/var/home/ptarjan/django/mysite/django/core/handlers/base.py" in get_response 86. response = callback(request, *callback_args, **callback_kwargs) File "/var/home/ptarjan/django/mysite/yourock/views/alias.py" in import_all 161. types.import_all(type, alias) File "/var/home/ptarjan/django/mysite/yourock/types/types.py" in import_all 52. return modules[type].import_all(siteAlias, alias) File "/var/home/ptarjan/django/mysite/yourock/types/xbox.py" in import_all 117. achiever = self.add_achievement(dict, siteAlias, alias) File "/var/home/ptarjan/django/mysite/yourock/types/base_profile.py" in add_achievement 130. owner = siteAlias, File "/var/home/ptarjan/django/mysite/django/db/models/query.py" in get 304. num = len(clone) File "/var/home/ptarjan/django/mysite/django/db/models/query.py" in __len__ 160. self._result_cache = list(self.iterator()) File "/var/home/ptarjan/django/mysite/django/db/models/query.py" in iterator 275. for row in self.query.results_iter(): File "/var/home/ptarjan/django/mysite/django/db/models/sql/query.py" in results_iter 206. for rows in self.execute_sql(MULTI): File "/var/home/ptarjan/django/mysite/django/db/models/sql/query.py" in execute_sql 1734. cursor.execute(sql, params) File "/var/home/ptarjan/django/mysite/django/db/backends/util.py" in execute 19. return self.cursor.execute(sql, params) File "/var/home/ptarjan/django/mysite/django/db/backends/mysql/base.py" in execute 83. return self.cursor.execute(query, args) File "/usr/lib/pymodules/python2.5/MySQLdb/cursors.py" in execute 151. query = query % db.literal(args) File "/usr/lib/pymodules/python2.5/MySQLdb/connections.py" in literal 247. return self.escape(o, self.encoders) File "/usr/lib/pymodules/python2.5/MySQLdb/connections.py" in string_literal 180. return db.string_literal(obj) Exception Type: UnicodeEncodeError at /import/xbox:bob Exception Value: 'ascii' codec can't encode character u'\u2122' in position 13: ordinal not in range(128) 

И перманентная часть модели:

 class Achievement(MyBaseModel): name = models.CharField(max_length=100, help_text="A human readable achievement name") 

Я использую бэкэнд MySQL с этим в моих настройках .py

 DEFAULT_CHARSET = 'utf-8' 

Итак, в основном, как я должен разбираться со всеми этими материалами в Юникоде? Я надеялся, что все это «просто сработает», если я останусь в стороне от забавных наборов персонажей и приклеился к UTF8. Увы, похоже, это не так просто.

7 Solutions collect form web for “python – Проблема сохранения символа Unicode для MySQL с Django”

Спасибо всем, кто разместил здесь. Это действительно помогает моему юникодному знанию (и хмурые другие люди чему-то научились).

Мы, казалось, все лаем по неправильному дереву, так как я пытался упростить свою проблему и не дал ВСЕ информацию. Кажется, что я не использовал строки «REAL» unicode, а скорее BeautifulSoup.NavigableString, которые отображались как строки unicode. Таким образом, все распечатки выглядели как unicode, но они не были.

Где-то глубоко в библиотеке MySQLDB они не могли справиться с этими строками.

Это сработало:

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

С другой стороны :

 >>> 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) 

Но это работает:

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

Итак, еще раз спасибо за всю помощь в Юникоде, я уверен, что это пригодится. Но сейчас …

ПРЕДУПРЕЖДЕНИЕ : BeautifulSoup не возвращает строки REAL unicode и должен быть принужден к использованию unicode (), прежде чем делать что-либо значимое с ними.

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

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

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

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

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

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

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

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

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

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

 a = models.Achievement(name=u"Played Mirror's Edge\u2122".encode("UTF-8")) 

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

Поэтому моя строка выглядит так: «mysql: // user: pass @ host: 3306 / database? Use_unicode = 1 & charset = utf8"

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

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

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

 from django.utils.safestring import SafeUnicode 

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

 unistr = SafeUnicode(unistr) 

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

оригинальный код, который давал проблемы (ht is beautifulsoup object): –

 keyword = ht.a.string 

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

 keyword = SafeUnicode(ht.a.string) 

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

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

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

 entry = unicode(sys.stdin, ENCODING) 

ENCODING зависело от языка, если я хорошо помню:

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

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

Мне кажется, что апостроф выглядит странно, если он не исчезнет так:

 u"Played Mirror\'s Edge\u2122" 
  • Граница Word для использования в тексте юникода для регулярного выражения Python
  • Эффективная обфускация строки Python
  • json.loads () возвращает объект unicode вместо словаря
  • Общая поддержка Unicode / UTF-8 для файлов csv в Python 2.6
  • Латинские символы Python и Unicode
  • Python __str__ против __unicode__
  • python, UnicodeEncodeError, преобразование unicode в ascii
  • Как узнать, скомпилирован ли Python с UCS-2 или UCS-4?
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.