使用Django和format-strings的UnicodeDecodeError

时间:2017-10-13 09:38:55

标签: python django format-string

我为每个人写了一个小问题的例子,看看使用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)

有人知道这里发生了什么吗?

5 个答案:

答案 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>]

参考:https://docs.python.org/2/howto/unicode.html

答案 4 :(得分:-1)

我不熟悉Django。您的问题似乎是在ASCI中表示实际上是unicode的文本数据。请在Python中尝试unidecode模块。

from unidecode import unidecode
#print(string) is replaced with 
print(unidecode(string))

参考Unidecode