Проблема при использовании входа в Python в Django и Unicode - PullRequest
7 голосов
/ 21 января 2010

полностью запутался сейчас ... Я занимаюсь разработкой на python / django и использую ведение журнала на python. Все мое приложение требует Unicode, и все мои модели имеют только методы unicode () `, return u '..'. Теперь при регистрации я столкнулся с действительно странной проблемой, что потребовалось много времени, чтобы обнаружить, что я могу воспроизвести ее. Я пробовал и Py 2.5.5 и Py 2.6.4 и то же самое. Итак

Всякий раз, когда я делаю прямую регистрацию, такую ​​как:

logging.debug(u'new value %s' % group) 

это вызывает группу моделей. Юникод (): вернуть юникод (group.name)

Все мои методы Unicode выглядят так:

def __unicode__(self):
    return u'%s - %s (%s)' % (self.group, self.user.get_full_name(), self.role)

Это работает, даже если group.name имеет значение XXX или ÄÄÄ (требуется Unicode). Но когда я по какой-то причине хочу записать набор, список, словарь, набор django-запросов и отдельные экземпляры, например, в. список может быть в юникоде или нет, у меня неприятности ...

Так что я получу UnicodeDecodingError всякий раз, когда для group.name требуется Unicode, такой как Luleå (мой родной город)

logging.debug(u'new groups %s' % list_of_groups)

Обычно я получаю такую ​​ошибку:

Exception Type:     UnicodeDecodeError
Exception Value:    ('ascii',  '<RBACInstanceRoleSet: s2 | \xc3\x84\xc3\x96\xc3\x96\xc3\x85\xc3\x85\xc3\x85 Gruppen>]', 106, 107, 'ordinal not in range(128)')

Но если я сделаю print list_of_groups, все будет хорошо на терминале

Итак, я понимаю, что список начинает генерировать себя и выполняет repr () для всех своих элементов, и они возвращают свои значения - в этом случае это должно быть 's2 | ÅÄÖÖ ', тогда список представляется как (ascii, the-stuff-in-the-list), а затем при попытке декодировать ascii в unicode это, конечно, не будет работать, так как один из элементы в списке восстановили u '...' самого себя, когда для него было выполнено repr.

Но почему это ???? ´

И почему все работает, и Unicode / Ascii обрабатываются правильно всякий раз, когда я регистрирую простые вещи, такие как group.name и т. Д. Или group, и вызываются методы unicode . Всякий раз, когда я становлюсь ленивым и хочу регистрировать список, набор или другие вещи, которые портятся, когда встречается символ Юникода ...

Еще несколько примеров, которые работают и терпят неудачу. Если group.name, я иду в поле модели и group вызывает __unicode__()

    logging.debug("1. group: %s " % group.name) # WORKS
    logging.debug(u"2. group: %s " % group) # WORKS
    logging.debug("3. group: %s " % group) # FAILS
    logging.debug(u"4. group: %s " % group.name) # WORKS
    logging.debug("5. group: %s " % group.name) # WORKS

... и я действительно думал, что у меня есть контроль над Unicode; - (

Ответы [ 9 ]

2 голосов
/ 17 сентября 2010

Вот мой тестовый код:

#-*- coding: utf-8 -*-                                      
class Wrap:                                          
    def __init__(self, s): self.s = s
    def __repr__(self): return repr(self.s)    
    def __unicode__(self): return unicode(self.s)
    def __str__(self): return str(self.s)

s = 'hello'  # a plaintext string
u = 'ÅÄÖÖ'.decode('utf-8') 
l = [s,u]
test0 = unicode(repr(l))
test1 = 'string %s' % l
test2 = u'unicode %s' % l

Выше работает нормально, когда вы запускаете его. Однако если вы измените объявление repr на: def repr (self): вернуть юникод (self.s)

Затем он прерывается с помощью:

Traceback (most recent call last):
  File "mytest.py", line 13, in <module> unicode(l)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3:
   ordinal not in range(128)

Таким образом, похоже, что кто-то в иерархии объектов имеет реализацию repr (), которая неправильно возвращает строку Юникода вместо обычной строки. Как уже упоминалось, когда вы делаете строку формата, такую ​​как

'format %s' % mylist

и mylist - это последовательность, python автоматически вызывает для нее функцию repr (), а не unicode () (поскольку не существует «правильного» способа представления списка в виде строки Unicode).

Возможно, здесь виноват django, или, возможно, вы неправильно внедрили __repr__ в одну из своих моделей.

#
1 голос
/ 06 мая 2010

Попробуйте использовать этот код в верхней части вашего views.py

#-*- coding: utf-8 -*-
...
1 голос
/ 21 января 2010

Я не могу воспроизвести вашу проблему с помощью простого теста:

Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15) 
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import logging
>>> group = u'Luleå'
>>> logging.warning('Group: %s', group)
WARNING:root:Group: Luleå
>>> logging.warning(u'Group: %s', group)
WARNING:root:Group: Luleå
>>> 

Итак, как говорит Даниэль, вероятно, есть что-то, что не соответствует Юникоду в том, что вы передаёте в лог.

Кроме того, я не знаю, какие обработчики вы используете, но убедитесь, что есть обработчики файлов, которые вы явно указываете используемую выходную кодировку, и если есть обработчики потоков, вы также оборачиваете любой выходной поток, который в этом нуждается. с оболочкой кодирования, например, предоставляемой модулем codecs (и передать упакованный поток в журнал).

0 голосов
/ 14 марта 2019

Я думаю, что эта ошибка Python является причиной описанного поведения https://bugs.python.org/issue19846 Проверьте настройки локали, если вы получаете UnicodeDecodeError на Python 3.

Этот ответ https://stackoverflow.com/a/40803148/4862792 помогает мне для Windows, но при работе с локалью LANG_C у меня возникла эта проблема еще раз

0 голосов
/ 25 ноября 2016

Проверка:

import locale
locale.getpreferredencoding()

должно быть 'utf8'. У меня есть «cp1252».

Помог мне добавить в manage.py:

import _locale
_locale._getdefaultlocale = (lambda *args: ['en_US', 'utf8'])

Windows 10, Django 1.10.3, Python 3.5.2, исправлены проблемы с русским языком

0 голосов
/ 21 сентября 2012

Я столкнулся с теми же проблемами: см. http://hustoknow.blogspot.com/2012/09/unicode-quirks-in-django.html.

Вы можете объявить метод str () для переопределения поведения Django по умолчанию, что поможет избежать этой проблемы. Или вы всегда должны ставить префикс u 'перед вашими выражениями logging ().

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

Вы пытались вручную сделать какой-либо результат Unicode?

logging.debug(u'new groups %s' % unicode(list_of_groups("UTF-8"))
0 голосов
/ 22 января 2010

Я закончил, следуя совету, когда отвечал, и перебирал весь код и делал понимание списка или подобное при попытке войти в набор запросов set / list / dict / django. Так что адаптация и добавление подобных вещей решили для меня:

logging.debug(u"new groups: %s" % [unicode(g) for g in list_of_groups])

Так что теперь все, что мне нужно сделать, это помнить, чтобы никогда не забывать делать это; -)

0 голосов
/ 21 января 2010

Я не понимаю, что вы не понимаете, если понимаете, о чем я. Ваш средний абзац:

Итак, я понимаю, что список начинает генерировать себя и выполняет repr () для всех своих элементов, и они возвращают свои значения - в этом случае это должно быть 's2 | ÅÄÖÖ ', тогда список представляется как (ascii, the-stuff-in-the-list), а затем при попытке декодировать ascii в unicode это, конечно, не сработает - поскольку один из элементов в списке восстановлен a u '...' самого себя, когда для него было сделано repr.

объясняет в точности, что происходит - вывод списка не то же самое, что печать всех его элементов, потому что под капотом все, что он делает, - это вызывает repr () для каждого элемента в списке. Вместо того, чтобы выводить необработанный список, вы можете зарегистрировать понимание списка, которое вызывает юникод для каждого элемента, что бы исправить это.

...