我正在看这个 问题 并开始想知道什么是 print 实际上确实如此。

我一直不知道如何使用 string.decode()string.encode() 在 python 交互式 shell 中以与 print 相同的格式获取 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'

编辑:

我为什么要问这个?我厌倦了 encode() 错误并意识到自从 print 可以做到(至少在交互式 shell 中)。我知道 一定有办法 神奇地进行编码 适当地, ,通过从某处挖掘要使用什么编码的信息......

附加信息:我在 linux2 上运行 Python 2.4.3 (#1, Sep 3 2009, 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'

然而,在同一个 Linux 机器上,结果与 Python 2.6.2 (r262:71600, Sep 8 2009, 13:06:43) 相同。

有帮助吗?

解决方案

编辑: (本次编辑与上一次编辑之间的重大变化......笔记:我在 Ubuntu 机器上使用 Python 2.6.4。)

首先,在我第一次尝试回答时,我提供了一些一般信息 printstr 我将把它留在下面,以方便任何遇到更简单问题的人 print 并偶然想到这个问题。至于处理OP遇到的问题的新尝试......基本上,我倾向于说这里没有灵丹妙药,如果 print 以某种方式设法理解奇怪的字符串文字,那么这不是可重现的行为。我通过终端窗口中与 Python 的以下有趣交互得出了这个结论:

>>> print '\xaa\xbb\xcc'
��

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

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

所以 '\xaa\xbb\xcc' 文字只有在解码时才有意义 作为 latin-1 文字 (好吧,实际上您可以使用与相关字符上的 latin-1 一致的不同编码)。至于 print 在你的情况下“只是工作”,它当然不适合我 - 如上所述。

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

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

请注意,没有解码错误和正确的输出(我希望在任何其他盒子上都能保持正确的输出)。显然,Python 可以理解你的字符串文字,但需要一些帮助。

这有帮助吗?(至少在理解事情是如何工作的方面,如果不是让编码的处理变得更容易的话......)


现在来看一些具有解释价值的有趣片段(希望如此)!这对我来说效果很好:

sys.stdout.write("\xAA\xBB\xCC".decode('latin1').encode(sys.stdout.encoding))

跳过解码或编码部分会导致与 unicode 相关的异常。从理论上讲,这是有道理的,因为需要第一次解码来决定给定字符串中有哪些字符(乍一看唯一明显的是 字节 有——Python 3 的想法是用(unicode)字符串表示字符,用字节表示字节,突然看起来非常合理),同时需要编码以便输出尊重输出流的编码。现在这个

sys.stdout.write("ąöî\n".decode(sys.stdin.encoding).encode(sys.stdout.encoding))

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

ord('ą'.decode('utf-8').encode('latin2'))

返回正确的 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()

至于实际执行情况 print, ,我预计这根本没有用,但如果你 真的 想知道发生了什么事...是在文件里的 Python/bltinmodule.c 在 Python 源代码中(我正在查看版本 2.6.4)。搜索以以下内容开头的行 builtin_print. 。实际上,这非常简单,没有任何魔法。:-)

希望这能回答您的问题...但是,如果您确实遇到了我完全忽略的更神秘的问题,请发表评论,我将进行第二次尝试。另外,我假设我们正在处理 Python 2.x;否则我想我不会有有用的评论。

其他提示

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

[编辑]如果你 看源码, ,得到 sys.stdout 然后调用:

PyFile_WriteObject(PyTuple_GetItem(args, i), file,
                 Py_PRINT_RAW);

我想魔法就在 Py_PRINT_RAW来源 只是说:

    if (flags & Py_PRINT_RAW) {
    value = PyObject_Str(v);
    }

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

>>> import sys
>>> a = '\xAA\xBB\xCC'
>>> print(a)
ª»Ì

全部 print 这里正在做的是写原始的 字节sys.stdout. 。字符串 a 是一串字节,而不是 Unicode 字符。

我为什么要问这个?我厌倦了encode() 错误,并意识到因为print 可以做到这一点(至少在交互式shell 中)。我知道这一定是一种神奇地正确编码的方法,通过从某个地方挖掘要使用什么编码的信息......

唉,不, print 这里没有做任何神奇的事情。你交给它一些字节,它会将字节转储到标准输出。

使用 .encode().decode() 正确地,您需要了解字节和字符之间的区别,恐怕您必须找出要使用的正确编码。

import sys

source_file_encoding = 'latin-1' # if there is no -*- coding: ... -*- line

a = '\xaa\xbb\xcc' # raw bytes that represent string in source_file_encoding

# print bytes, my terminal tries to interpret it as 'utf-8'
sys.stdout.write(a+'\n') 
# -> ��

ua = a.decode(source_file_encoding)
sys.stdout.write(ua.encode(sys.stdout.encoding)+'\n')
# -> ª»Ì

定义 Python 源代码编码

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top