Python:如何强制“打印”使用__unicode__而不是__str__,或者自然地“打印”消息而不显式调用unicode()

时间:2011-11-22 05:11:11

标签: python string unicode character-encoding cjk

基本上我只希望能够使用名为Bottle的类创建实例:例如class Bottle(object):...然后在另一个模块中能够简单地“打印”任何实例而不用不得不破解用于显式调用字符编码例程的代码。

总之,当我尝试:

obj=Bottle(u"味精")
print obj

或“到位”“打印”:

print Bottle(u"味精")

我明白了:

"UnicodeEncodeError: 'ascii' codec can't encode characters"

类似的stackoverflow问题:

¢目前切换到python3是不可行的。 ¢

关于如何进行utf-8打印的解决方案或提示(和解释)(就像U类成功一样)将非常感激。 : - )

ThanX N

-

示例代码:

-------- 8>< - - - - 在这里切 - - - -

#!/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>< - - - - 剪这里 - - - - 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>< - - - - 剪这里 - - - - 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 个答案:

答案 0 :(得分:6)

如果您使用sys.stdout = codecs.getwriter(encoding)(sys.stdout),则应将Unicode字符串传递给print

>>> 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-friendly 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字符串的情况。