Я принял бы (с @eed3s9n), что он должен способствовать слабой связи. Кроме того, без интерфейсов поблочное тестирование становится намного более трудным, поскольку Вы не можете копировать свои объекты.
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.
Вы используете строки типа unicode. Если ваша модель или серверная часть SQL не поддерживает их или не знает, как преобразовать в UTF-8, просто выполните преобразование самостоятельно. Придерживайтесь простых строк (тип python str) и конвертируйте, как в
a = models.Achievement(name=u"Played Mirror's Edge\u2122".encode("UTF-8"))
Я согласен с Николаем. Я уже столкнулся с проблемой использования 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 ?
Я работал над этим вчера и обнаружил, что добавление "charset = utf8" и "use_unicode = 1" в строку подключения заставило его работать (используя SQLAlchemy, думаю, это та же проблема) .
Итак, моя строка выглядит так: "mysql: // user: pass @ host : 3306 / database? use_unicode = 1 & charset = utf8"
Для меня апостроф выглядит странно, если его не экранировать следующим образом:
u"Played Mirror\'s Edge\u2122"
Несколько замечаний:
Python 2.x имеет два строковых типа
Экземпляры этих типов считаются «декодированными» данными. Внутреннее представление - это ссылка, поэтому вы «декодируете» в него внешние данные и «кодируете» в некоторый внешний формат.
Хорошая стратегия - декодировать как можно раньше, когда данные поступают в систему, и кодировать как можно позже возможное. Постарайтесь как можно больше использовать Unicode для строк в вашей системе. (Я не согласен с Николаем в этом отношении.)
Этот аспект кодирования применим к ответу Николая. Он берет исходную строку Unicode и кодирует ее в utf-8. Но это не t решить проблему (по крайней мере, в общем случае), потому что результирующий байтовый буфер может по-прежнему содержать байты вне диапазона (127) (я не проверял наличие \ u2122), что означает, что вы будете снова попадет в то же исключение.
Тем не менее, анализ Николая показывает, что вы передаете строку Unicode, но где-то в системе это считается экземпляром str. Достаточно, если где-то к вашему аргументу unicode применяется функция str ().
В этом случае Python использует так называемую кодировку по умолчанию, которая является ascii, если вы не измените ее. Существует функция sys.setdefaultencoding, которую вы можете использовать для переключения, например, на utf-8, но эта функция доступна только в ограниченном контексте, поэтому вы не можете легко использовать ее в коде приложения.
Я чувствую, что проблема где-то глубже в слои, которые вы вызываете. К сожалению, Я не могу комментировать Django или MySQL / SQLalchemy, но мне интересно, можете ли вы указать тип Unicode при объявлении атрибута name в вашей модели. Было бы хорошей практикой БД обрабатывать информацию о типе на уровне поля. Может быть, есть альтернатива CharField?!
И да, вы можете безопасно вставить одинарную кавычку (') в строку с двойными кавычками ("), и наоборот.
У меня были похожие проблемы с 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, все, что я знаю, это решило мои проблемы.