我为每个人写了一个小问题的例子,看看使用Python 2.7和Django 1.10.8发生了什么
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals, print_function
import time
from django import setup
setup()
from django.contrib.auth.models import Group
group = Group(name='schön')
print(type(repr(group)))
print(type(str(group)))
print(type(unicode(group)))
print(group)
print(repr(group))
print(str(group))
print(unicode(group))
time.sleep(1.0)
print('%s' % group)
print('%r' % group) # fails
print('%s' % [group]) # fails
print('%r' % [group]) # fails
退出以下输出+追溯
$ python .PyCharmCE2017.2/config/scratches/scratch.py
<type 'str'>
<type 'str'>
<type 'unicode'>
schön
<Group: schön>
schön
schön
schön
Traceback (most recent call last):
File "/home/srkunze/.PyCharmCE2017.2/config/scratches/scratch.py", line 22, in <module>
print('%r' % group) # fails
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 11: ordinal not in range(128)
有人知道这里发生了什么吗?
答案 0 :(得分:6)
这里的问题是您正在将UTF-8字节串插入到Unicode字符串中。您的from __future__ import unicode_literals
字符串是Unicode字符串,因为您使用了repr(group)
,但%r
(由repr()
占位符使用)返回字节字符串。对于Django模型,repr()
可以在表示中包含Unicode数据,使用UTF-8编码为字节串。此类表示不是ASCII安全。
对于您的具体示例,Group
实例上的'<Group: sch\xc3\xb6n>'
生成字节字符串>>> u'%s' % '<Group: sch\xc3\xb6n>'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 11: ordinal not in range(128)
。将其插值为 Unicode 字符串会触发隐式解码:
from __future__ import unicode_literals
请注意,我的Python会话中没有使用'<Group: sch\xc3\xb6n>'
,因此unicode
字符串不是str
对象,它是from __future__ import unicode_literals
bytestring对象!
在Python 2中,您应该避免混合使用Unicode和字节字符串。始终显式规范化您的数据(将Unicode编码为字节或将字节解码为Unicode)。
如果必须使用b
,仍然可以使用>>> from __future__ import unicode_literals
>>> type('') # empty unicode string
<type 'unicode'>
>>> type(b'') # empty bytestring, note the b prefix
<type 'str'>
>>> b'%s' % b'<Group: sch\xc3\xb6n>' # two bytestrings
'<Group: sch\xc3\xb6n>'
前缀创建字节串:
BarConfig.cmake
答案 1 :(得分:3)
我很难找到问题的一般解决方案。
__repr__()
是我理解应该返回str的,任何改变它的努力似乎都会引起新的问题。
关于在项目外定义__repr__()
方法的事实,您可以重载方法。例如
def new_repr(self):
return 'My representation of self {}'.format(self.name)
Group.add_to_class("__repr__", new_repr)
我能找到的唯一解决办法就是明确告诉解释器如何处理字符串。
from __future__ import unicode_literals
from django.contrib.auth.models import Group
group = Group(name='schön')
print(type(repr(group)))
print(type(str(group)))
print(type(unicode(group)))
print(group)
print(repr(group))
print(str(group))
print(unicode(group))
print('%s' % group)
print('%r' % repr(group))
print('%s' % [str(group)])
print('%r' % [repr(group)])
# added
print('{}'.format([repr(group).decode("utf-8")]))
print('{}'.format([repr(group)]))
print('{}'.format(group))
在python 2.x中使用字符串是一团糟。 希望这能为我们提供一些解决方法(这是我能找到的唯一方法)。
答案 2 :(得分:1)
我认为真正的问题在于django代码。
六年前有报道:
https://code.djangoproject.com/ticket/18063
我认为django的补丁会解决它:
def __repr__(self):
return self.....encode('ascii', 'replace')
我认为repr()方法应该返回&#34; 7位ascii&#34;。
答案 3 :(得分:-1)
如果是这种情况,那么我们需要使用我们的自定义方法覆盖unicode方法。试试下面的代码。它会工作。我测试了它。
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
from django.contrib.auth.models import Group
def custom_unicode(self):
return u"%s" % (self.name.encode('utf-8', 'ignore'))
Group.__unicode__ = custom_unicode
group = Group(name='schön')
# Tests
print(type(repr(group)))
print(type(str(group)))
print(type(unicode(group)))
print(group)
print(repr(group))
print(str(group))
print(unicode(group))
print('%s' % group)
print('%r' % group)
print('%s' % [group])
print('%r' % [group])
# output:
<type 'str'>
<type 'str'>
<type 'unicode'>
schön
<Group: schön>
schön
schön
schön
<Group: schön>
[<Group: schön>]
[<Group: schön>]
答案 4 :(得分:-1)
我不熟悉Django。您的问题似乎是在ASCI中表示实际上是unicode的文本数据。请在Python中尝试unidecode模块。
from unidecode import unidecode
#print(string) is replaced with
print(unidecode(string))