Python从__str__给出“序数不在范围内”错误,但不从print中给出

时间:2014-07-01 18:13:20

标签: python unicode encoding

我有一个从JSON文件中读取一些数据的对象。一些JSON数据是拉丁语1个字符的字符串,例如:

"name" : "frisée"

我将此对象字符串化为一个表,其中包含从JSON对象读取的一些字符串。如果我写这个:

def __str__(self): # Never mind the details, what matters is that I use __str__
    ts = [p + (count,) for p, count in self.counts.items()]
    ts.sort(key=lambda x:(x[2], x[0], x[1]))
    return "\n".join(["%s\t%s\t%s" % (t[0], t[1], t[2]) for t in ts])

然后尝试运行print MyObject()我收到错误:

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 9112: ordinal not in range(128)

但是,如果我这样写:

def to_string(self):
    ts = [p + (count,) for p, count in self.counts.items()]
    ts.sort(key=lambda x:(x[2], x[0], x[1]))
    return "\n".join(["%s\t%s\t%s" % (t[0], t[1], t[2]) for t in ts])

然后运行print MyObject().to_string()一切正常。正确打印“é”字符。

为什么__str__的行为与to_string不同?如何正确打印__str__版本?

我尝试了encode的各种迭代但无济于事。

1 个答案:

答案 0 :(得分:1)

您的__str__正在返回 unicode 类型值; JSON字符串始终是Unicode。但是,__str__ result must always return a bytestring, so type str。如果你不这样做,Python会为你调用str()结果,这意味着它会使用默认的ASCII编解码器隐式编码任何Unicode。

对结果进行明确编码:

def __str__(self):
    ts = [p + (count,) for p, count in self.counts.items()]
    ts.sort(key=lambda x:(x[2], x[0], x[1]))
    return u'\n'.join([u'\t'.join(t[:2]) for t in ts]).encode('utf8')

或使用__unicode__ method代替。但print不会调用此方法。您必须明确使用print unicode(MyObject())

print知道如何正确编码unicode字符串,前提是您的终端配置正确。它将使用sys.stdout.encoding显式编码您的Unicode数据。这就是MyObject().to_string()有效的原因。