我有字符串
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")
我在settings.py
中使用了MySQL后端DEFAULT_CHARSET = 'utf-8'
基本上,我应该如何处理所有这些unicode的东西?如果我远离有趣的角色并坚持使用UTF8,我希望它能“正常工作”。唉,这似乎并不那么容易。
答案 0 :(得分:12)
感谢在此发帖的所有人。它真的有助于我的unicode知识(并且让其他人学到了很多东西)。
因为我试图简化我的问题并且没有提供所有信息,所以我们似乎都在咆哮错误的树。似乎我没有使用“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™>
所以,再次感谢所有的unicode帮助,我相信它会派上用场。但是现在......
警告:BeautifulSoup不会返回 REAL unicode字符串,应该在执行任何有意义的操作之前强制使用unicode()。
答案 1 :(得分:4)
一些评论:
Python 2.x有两种字符串类型
这些类型的实例被视为“已解码”数据。内部表示是参考,因此您将外部数据“解码”到其中,并“编码”为某种外部格式。
一个好的策略是在数据进入系统时尽早解码,并尽可能晚地编码。尝试尽可能地为系统中的字符串使用unicode。 (在这方面我不同意尼古拉)。
此编码方面适用于Nicolai的答案。他获取原始的unicode字符串,并将其编码为utf-8。但是这个没有解决问题(至少不是一般),因为结果字节缓冲区仍然包含范围之外的字节(127)(我没有检查过) for \ u2122),这意味着你会再次遇到同样的异常。
仍然Nicolai的分析认为你传递的是一个unicode字符串,但在系统的某个地方,这被认为是一个str实例。如果某个地方将str()函数应用于你的unicode参数就足够了。
在这种情况下,Python使用所谓的默认编码,如果不更改它,则为ascii。有一个函数sys.setdefaultencoding,您可以使用它来切换到例如utf-8,但该功能仅在有限的上下文中可用,因此您无法在应用程序代码中轻松使用它。
我的感觉是问题在于你所呼唤的层次更深层。不幸的是,我无法评论Django或MySQL / SQLalchemy,但我想知道在模型中声明'name'属性时是否可以指定unicode类型。在字段级别处理类型信息将是一种很好的数据库实践。也许还有CharField的替代品?!
是的,您可以安全地在双引号(“)字符串中嵌入单引号('),反之亦然。
答案 2 :(得分:3)
您正在使用'unicode'类型的字符串。如果您的模型或SQL后端不支持它们或者不知道如何转换为UTF-8,那么只需自己进行转换即可。坚持使用简单的字符串(python类型str)并转换为
a = models.Achievement(name=u"Played Mirror's Edge\u2122".encode("UTF-8"))
答案 3 :(得分:1)
昨天我正在研究这个问题,我发现在连接字符串中添加“charset = utf8”和“use_unicode = 1”使其工作(使用SQLAlchemy,猜测它是同样的问题)。
所以我的字符串看起来像: “MySQL的://用户:通过@主机:3306 /数据库use_unicode = 1&安培;字符集= UTF8”
答案 4 :(得分:0)
我同意尼古拉的观点。我已经遇到过使用UTF-8的问题,即使在纯Python(2.5)中也是如此。
我终于使用了unicode函数(?):
entry = unicode(sys.stdin, ENCODING)
如果记得很清楚,ENCODING取决于语言环境:
import sys, locale
ENCODING = locale.getdefaultlocale()[1]
DEFAULT_ENCODING = sys.getdefaultencoding()
也许看看Python Unicode HOWTO?
答案 5 :(得分:0)
我遇到了与mysql和postgres类似的问题,但sqllite没有问题。
这就是我用postgres解决这个问题的方法(没有用mysql测试这个技巧但是id也可以解决它)
在你正在处理unicode字符串的文件中执行
from django.utils.safestring import SafeUnicode
并假设unistr是包含字符串的变量,执行
unistr = SafeUnicode(unistr)
在我的情况下,我正在从网站上抓取
给出问题的原始代码(ht是beautifulsoup对象): -
keyword = ht.a.string
修复: -
keyword = SafeUnicode(ht.a.string)
我不知道为什么或者SafeUnicode正在做什么,我所知道的是它解决了我的问题。
答案 6 :(得分:-1)
对我来说,撇号看起来很奇怪,如果不是这样的话:
u"Played Mirror\'s Edge\u2122"