Python:如何强制“print”使用__unicode__而非__str__,或自然“print”消息而无需显式调用unicode()
基本上,我想用一个叫做Bottle的类来创建实例,比如说 class Bottle(object):...
,然后在另一个模块中能够简单地“打印”任何实例,而不需要去修改代码来专门调用字符编码的程序。
总结一下,当我尝试:
obj=Bottle(u"味精")
print obj
或者进行“就地”打印:
print Bottle(u"味精")
我得到的结果是:
"UnicodeEncodeError: 'ascii' codec can't encode characters"
类似的StackOverflow问题:
¢ 目前还不能切换到python3. ¢
如果能提供一个解决方案或提示(以及解释),告诉我如何进行就地的utf-8打印(就像下面的类U那样成功)我会非常感激。:-)
谢谢 N
--
示例代码:
-------- 8>< - - - - cut here - - - -
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def setdefaultencoding(encoding="utf-8"):
import sys, codecs
org_encoding = sys.getdefaultencoding()
if org_encoding == "ascii": # not good enough
print "encoding set to "+encoding
sys.stdout = codecs.getwriter(encoding)(sys.stdout)
sys.stderr = codecs.getwriter(encoding)(sys.stderr)
setdefaultencoding()
msg=u"味精" # the message!
class U(unicode): pass
m1=U(msg)
print "A)", m1 # works fine, even with unicode, but
class Bottle(object):
def __init__(self,msg): self.msg=msg
def __repr__(self):
print "debug: __repr__",self.msg
return '{{{'+self.msg+'}}}'
def __unicode__(self):
print "debug: __unicode__",self.msg
return '{{{'+self.msg+'}}}'
def __str__(self):
print "debug: __str__",self.msg
return '{{{'+self.msg+'}}}'
def decode(self,arg): print "debug: decode",self.msg
def encode(self,arg): print "debug: encode",self.msg
def translate(self,arg): print "debug: translate",self.msg
m2=Bottle(msg)
#print "B)", str(m2)
print "C) repr(x):", repr(m2)
print "D) unicode(x):", unicode(m2)
print "E)",m2 # gives: UnicodeEncodeError: 'ascii' codec can't encode characters
-------- 8>< - - - - cut here - - - - Python 2.4 输出:
encoding set to utf-8
A) 味精
C) repr(x): debug: __repr__ 味精
{{{\u5473\u7cbe}}}
D) unicode(x): debug: __unicode__ 味精
{{{味精}}}
E) debug: __str__ 味精
Traceback (most recent call last):
File "./uc.py", line 43, in ?
print "E)",m2 # gives: UnicodeEncodeError: 'ascii' codec can't encode characters
UnicodeEncodeError: 'ascii' codec can't encode characters in position 3-4: ordinal not in range(128)
-------- 8>< - - - - cut here - - - - Python 2.6 输出:
encoding set to utf-8
A) 味精
C) repr(x): debug: __repr__ 味精
Traceback (most recent call last):
File "./uc.py", line 41, in <module>
print "C) repr(x):", repr(m2)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 3-4: ordinal not in range(128)
相关问题:
1 个回答
如果你使用 sys.stdout = codecs.getwriter(encoding)(sys.stdout)
,那么你在用 print
打印的时候应该传入 Unicode 字符串:
>>> print u"%s" % Bottle(u"魯賓遜漂流記")
debug: __unicode__ 魯賓遜漂流記
{{{魯賓遜漂流記}}}
正如 @bobince 在评论中提到的:尽量避免以这种方式改变 sys.stdout
,否则可能会影响到任何依赖 sys.stdout
的库代码,这些代码可能不支持打印 Unicode 字符串。
一般来说:
__unicode__()
应该返回 Unicode 字符串:
def __init__(self, msg, encoding='utf-8'):
if not isinstance(msg, unicode):
msg = msg.decode(encoding)
self.msg = msg
def __unicode__(self):
return u"{{{%s}}}" % self.msg
__repr__()
应该返回适合 ASCII 的 str
对象:
def __repr__(self):
return "Bottle(%r)" % self.msg
__str__()
应该返回 str
对象。可以选择性地添加 encoding 来说明使用了什么编码。这里没有好的方法来选择编码:
def __str__(self, encoding="utf-8")
return self.__unicode__().encode(encoding)
定义 write()
方法:
def write(self, file, encoding=None):
encoding = encoding or getattr(file, 'encoding', None)
s = unicode(self)
if encoding is not None:
s = s.encode(encoding)
return file.write(s)
这个方法应该处理文件有自己编码或者直接支持 Unicode 字符串的情况。