Python 打印对象和unicode,什么';引擎盖下面有什么?好的指导方针是什么?

Python 打印对象和unicode,什么';引擎盖下面有什么?好的指导方针是什么?,python,unicode,printing,stdout,Python,Unicode,Printing,Stdout,我正在努力进行打印和unicode转换。下面是在2.5 windows解释器中执行的一些代码 >>> import sys >>> print sys.stdout.encoding cp850 >>> print u"é" é >>> print u"é".encode("cp850") é >>> print u"é".encode("utf8") ├® >>> print u"é".

我正在努力进行打印和unicode转换。下面是在2.5 windows解释器中执行的一些代码

>>> import sys
>>> print sys.stdout.encoding
cp850
>>> print u"é"
é
>>> print u"é".encode("cp850")
é
>>> print u"é".encode("utf8")
├®
>>> print u"é".__repr__()
u'\xe9'

>>> class A():
...    def __unicode__(self):
...       return u"é"
...
>>> print A()
<__main__.A instance at 0x0000000002AEEA88>

>>> class B():
...    def __repr__(self):
...       return u"é".encode("cp850")
...
>>> print B()
é

>>> class C():
...    def __repr__(self):
...       return u"é".encode("utf8")
...
>>> print C()
├®

>>> class D():
...    def __str__(self):
...       return u"é"
...
>>> print D()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0: ordinal not in range(128)

>>> class E():
...    def __repr__(self):
...       return u"é"
...
>>> print E()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0: ordinal not in range(128)

谢谢

我假定您的
sys.getdefaultencoding()
仍然是“ascii”。我认为每当应用对象的str()或repr()时,都会用到它。您可以使用
sys.setdefaultencoding()
更改此设置。但是,一旦您写入流,无论是标准输出还是文件,都必须遵守其编码。依我看,这也适用于shell上的管道。我假设“print”遵守标准输出编码,但在构造参数时,异常发生在调用“print”之前。

Python对给定的函数和方法没有太多语义类型约束,但它有一些约束,下面是其中之一:
\uu str\uuu
(在Python 2中。*)必须返回字节字符串。通常,如果在需要字节字符串的位置找到unicode对象,则在尝试从相关unicode对象生成所需字节字符串时,将应用当前默认编码(通常为
'ascii'

对于此操作,编码(如果有)对任何给定文件对象的调用都是不相关的,因为从
\uuuuu str\uuuuuu
返回的内容可能即将被打印出来,或者可能会受到完全不同和不相关的处理。调用
\uuuuuu str\uuuuuu
的目的与调用本身及其结果无关;Python通常不考虑这一点在确定操作的语义时,操作的“未来上下文”(操作完成后,您将对结果执行什么操作)

这是因为Python并不总是知道你未来的意图,它会尽量减少意外的发生。
print str(x)
s=str(x);print s
(一次吞咽与两次吞咽中执行的相同操作)尤其必须具有相同的效果;如果是第二种情况,则如果
str(x)将出现异常
无法有效地生成字节字符串(例如,
x.\uuu str\uuu()
无法),因此在另一种情况下也应发生异常

print
本身(我相信从2.4开始)在使用unicode对象时,会考虑目标流的
.encoding
属性(如果有的话)(默认情况下是
sys.stdout
);其他尚未连接到任何给定目标流的操作——以及
str(x)
(即
x.\uu str uuuuuuu()
)就是这样一个行动

希望这有助于说明恼人行为的原因

编辑:OP现在澄清了“我的主要问题是使类“可打印”,即print a()打印完全可读的内容(不使用\x***unicode字符)。”。我认为以下方法最适合实现这一特定目标:

import sys

DEFAULT_ENCODING = 'UTF-8'  # or whatever you like best

class sic(object):

    def __unicode__(self):  # the "real thing"
        return u'Pel\xe9'

    def __str__(self):      # tries to "look nice"
        return unicode(self).encode(sys.stdout.encoding or DEFAULT_ENCODING,
                                    'replace')

    def __repr__(self):     # must be unambiguous
        return repr(unicode(self))
也就是说,这种方法将
\uuuuuunicode\uuuuu
作为类实例自身格式化的主要方式——但是因为(在Python 2中)
print
调用
\uuuuu str\uuuu
相反,它有一个委托给
\uuuuuu unicode\uuuuu
,在编码方面它能做的最好。这不是完美的,但是Python 2的
print
语句无论如何都远不是完美的;-)


\uuuu repr\uuuuu
本身必须努力做到明确,也就是说,为了“好看”而冒着模棱两可的风险(理想情况下,如果可行,它应该返回一个字节字符串,如果传递给
eval
,将使一个实例与当前实例相等……这远非总是可行的,但缺少歧义是
\uu str\uuu
\uu repr\uuu
之间区别的绝对核心建议尊重这一区别!)。

谢谢Alex,我现在明白了为什么
print D()
的行为与
print D()。\uuu str\uuu()
不同了。这有点让人困惑。那么,当您需要在repr或str方法中处理unicode字符串时,您能分享一些指导原则吗?我应该返回repr()吗或者我仍然可以在自定义站点模块中使用sys.setdefaultencoding返回一个unicode并设置编码(但我发现这太麻烦了)@Thorfin,要返回Unicode,实现
\uuuuUnicode\uuuuu
\uuuu str\uuuu
应该始终返回一个字节字符串,
\uuu repr\uuuu
应该始终返回一个“理想”的字节字符串(但这并不总是可能或合理的)人们可以
eval
来构建一个新对象。我相信
\uuuunicode\uuuunicode>只能与unicode()一起调用,不幸的是,这并不能解决我的问题。我在最初问题的末尾添加了一些信息。再次感谢。
\uuuu repr\uuuu
应该返回完全明确的输出——让它避免输出中的转义序列将是一件令人憎恶的事(请不要这样做!)。编辑A以显示实现特定期望结果的最佳方式。谢谢!我非常理解repr返回明确输出的必要性。当我看到您的示例时,我正在完成相同的行为,只是
return repr(self.\uu unicode\uu())
而不是
return repr(unicode(self))
。我相信/希望是一样的。
import sys

DEFAULT_ENCODING = 'UTF-8'  # or whatever you like best

class sic(object):

    def __unicode__(self):  # the "real thing"
        return u'Pel\xe9'

    def __str__(self):      # tries to "look nice"
        return unicode(self).encode(sys.stdout.encoding or DEFAULT_ENCODING,
                                    'replace')

    def __repr__(self):     # must be unambiguous
        return repr(unicode(self))