python print()函数实际上做了什么?

Kim*_*ais 9 python printing unicode python-2.x

我正在看这个问题,并开始想知道print实际上做了什么.

我从来没有发现如何使用string.decode()string.encode()在python交互式shell中以与打印相同的格式获取unicode字符串"out".无论我做什么,我都会得到

  1. UnicodeEncodeError或
  2. 带有"\ x ##"表示法的转义字符串...

这是python 2.x,但我已经尝试修改我的方式并实际调用print():)

例:

>>> import sys
>>> a = '\xAA\xBB\xCC'
>>> print(a)
ª»Ì
>>> a.encode(sys.stdout.encoding)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0xaa in position 0: ordinal not in range(128)
>>> a.decode(sys.stdout.encoding)
u'\xaa\xbb\xcc'
Run Code Online (Sandbox Code Playgroud)

编辑:

我为什么这么问?我厌倦了encode()错误,并意识到,因为print可以做到(至少在交互式shell中).我知道一定有办法神奇地做编码PROPERLY,通过下挖信息从什么地方用什么编码?

附加信息:我在linux2上运行Python 2.4.3(#1,2009年9月3日,15:37:12)[GCC 4.1.2 20080704(Red Hat 4.1.2-46)]

>>> sys.stdin.encoding
'ISO-8859-1'
>>> sys.stdout.encoding
'ISO-8859-1'
Run Code Online (Sandbox Code Playgroud)

但是,在同一个Linux机器上的结果与Python 2.6.2(r262:71600,2009年9月8日,13:06:43)相同.

Mic*_*zyk 9

编辑:(此编辑与前一个编辑之间的重大更改...注意:我在Ubuntu框中使用Python 2.6.4.)

首先,我在回答第一个尝试,我所提供的一般信息,print而且str这我要去下面要离开有任何简单的问题与利益print,并就这个问题chancing.至于处理OP遇到的问题的新尝试......基本上,我倾向于说这里没有银弹,如果print以某种方式设法理解一个奇怪的字符串文字,那么这不是可重现的行为.我在终端窗口中通过以下与Python的有趣交互得出了这个结论:

>>> print '\xaa\xbb\xcc'
??
Run Code Online (Sandbox Code Playgroud)

您是否尝试直接从终端输入ª»Ì?在使用utf-8作为编码的Linux终端上,这实际上是以六个字节读入的,然后可以借助该decode方法使其看起来像三个unicode字符:

>>> 'ª»Ì'
'\xc2\xaa\xc2\xbb\xc3\x8c'
>>> 'ª»Ì'.decode(sys.stdin.encoding)
u'\xaa\xbb\xcc'
Run Code Online (Sandbox Code Playgroud)

因此,'\xaa\xbb\xcc'如果您将其解码为latin-1文字,那么文字才有意义(实际上,您可以使用与相关字符上的latin-1一致的不同编码).至于print你的情况下"正常工作",它肯定不适合我 - 如上所述.

这是因为当您使用不带前缀的字符串文字时u- "asdf"而不是u"asdf"- 结果字符串将使用一些非unicode编码.没有; 事实上,字符串对象本身将是编码 - 不知道,并且您将不得不将其视为使用编码x进行编码,以获得正确的x值.这个基本想法让我得到以下结论:

a = '\xAA\xBB\xCC'
a.decode('latin1')
# result: u'\xAA\xBB\xCC'
print(a.decode('latin1'))
# output: ª»Ì
Run Code Online (Sandbox Code Playgroud)

注意缺少解码错误和正确的输出(我希望在任何其他方框保持正确).显然你的字符串文字可以通过Python理解,但不是没有一些帮助.

这有帮助吗?(至少在了解事情是如何工作的情况下,如果不是更容易处理编码......)


现在为一些有趣的位有一些解释价值(希望)!这对我来说很好:

sys.stdout.write("\xAA\xBB\xCC".decode('latin1').encode(sys.stdout.encoding))
Run Code Online (Sandbox Code Playgroud)

跳过解码或编码部分会导致与unicode相关的异常.从理论上讲,这是有道理的,因为需要第一个解码来决定给定字符串中的字符(第一眼看到的唯一明显的是字节是什么- Python 3为字符设置(unicode)字符串的想法和字节,以及字节,突然看起来非常合理),而需要编码,以便输出尊重输出流的编码.现在这个

sys.stdout.write("?öî\n".decode(sys.stdin.encoding).encode(sys.stdout.encoding))
Run Code Online (Sandbox Code Playgroud)

也按预期工作,但字符实际上来自键盘,因此实际上使用stdin编码编码...此外,

ord('?'.decode('utf-8').encode('latin2'))
Run Code Online (Sandbox Code Playgroud)

返回正确的177(我的输入编码是utf-8),但'\ xc4\x85'.encode('latin2')对Python没有任何意义,因为它不知道如何理解'\ xc4\x85'和数字,尝试'ascii'代码是它能做的最好的.


原答案:

Python文档的相关部分(对于版本2.6.4)说这print(obj)意味着打印出给出的字符串str(obj).我想你可以将它包装在一个调用unicode(如unicode(str(obj)))中以获取一个unicode字符串 - 或者你可以只使用Python 3并将这种特殊的麻烦交换给几个不同的字符串.;-)

顺便说一下,这表明您可以操纵print对象的结果,就像您可以操纵调用str对象的结果一样,即通过弄乱__str__方法.例:

class Foo(object):
    def __str__(self):
        return "I'm a Foo!"

print Foo()
Run Code Online (Sandbox Code Playgroud)

至于实际的实现print,我希望这根本不会有用,但如果你真的想知道发生了什么......它Python/bltinmodule.c在Python源文件中(我正在看2.6.4版本) .搜索以builtin_print.开头的行.它实际上完全是直截了当的,没有任何魔力在那里.:-)

希望这能回答你的问题...但如果你确实有一个我完全错过的更为神秘的问题,请做评论,我会再做一次.另外,我假设我们正在处理Python 2.x; 否则我想我不会有一个有用的评论.


Aar*_*lla 5

print()用于sys.stdout.encoding确定输出控制台可以理解的内容,然后在调用中使用此编码str.encode().

[编辑]如果您查看源代码,它会获取sys.stdout然后调用:

PyFile_WriteObject(PyTuple_GetItem(args, i), file,
                 Py_PRINT_RAW);
Run Code Online (Sandbox Code Playgroud)

我想魔法已经存在,Py_PRINT_RAW消息来源只是说:

    if (flags & Py_PRINT_RAW) {
    value = PyObject_Str(v);
    }
Run Code Online (Sandbox Code Playgroud)

所以这里没有魔力.对参数的循环sys.stdout.write(str(item))应该可以解决问题.

  • @Kimvais:我抬头看了看源头.没有魔法. (2认同)