为什么打印这些值在不同的操作系统和版本中给出不同的值?



为什么打印这些\x值在不同的操作系统和版本中给出不同的值? 例:

print("A"*20+"xefxbexadxde")

这在 Python3 和 2 以及不同的平台中提供了不同的输出

在Microsoft的窗口中:

蟒蛇2:AAAAAAAAAAAAAAAAAAAAï¾Þ

Python3:AAAAAAAAAAAAAAAAAAAAï¾Þ

在卡利:

蟒蛇2:AAAAAAAAAAAAAAAAAAAAᆳ

蟒蛇3:AAAAAAAAAAAAAAAAAAAAï¾­Þ

更新:我想要的是确切的 Python2 输出,但使用 Python3?我尝试了很多东西(编码,解码,字节转换),但意识到\xde无法解码。还有其他方法可以实现我想要的吗?

这是一个编码问题。

在拉丁语 1 或 Windows 1252 编码中,您有:

0xef -> ï (LATIN SMALL LETTER I WITH DIAERESIS)
0xbe -> ¾ (VULGAR FRACTION THREE QUARTERS)
0xad -> undefined and non printed in your examples
0xde -> Þ (LATIN CAPITAL LETTER THORN)

在 utf-8 编码中,您有:

'xefxbexad'->u'uffad''ᆳ'(半角韩文字母里厄尔-西奥斯)'xde'-> 应该引发一个 UnicodeDecodeError...

在Windows中,Python2或Python3都使用Windows 1252代码页(在您的示例中)。在 Kali 上,Python2 将字符串视为字节字符串,终端以 utf8 显示它,而 Python3 假设它已经包含 unicode 字符值并直接显示它们。

与拉丁语1(以及Windows 1252中0x80-0x9f以外的所有字符)一样,字节码是Unicode值,足以解释您的输出。

要学习的内容:明确字符串是否包含 unicode 或字节,并注意编码!

要在 Python2 和 Python 3 上获得一致的行为,您需要明确预期输出。如果你愿意,AAAAAAAAAAAAAAAAAAAAᆳ,那么xde就是垃圾;如果你想要AAAAAAAAAAAAAAAAAAAAï¾Þxad就是垃圾。无论哪种方式,打印现有内容的"解决方案"是显式使用bytes文字并使用所需的编码decode它们,忽略错误。因此,要获得AAAAAAAAAAAAAAAAAAAAᆳ(解释为 UTF-8),您需要执行以下操作:

print((b"A"*20+b"xefxbexadxde").decode('utf-8', errors='ignore'))

而要获得AAAAAAAAAAAAAAAAAAAAï¾Þ你会这样做:

# cp1252 can be used instead of latin-1, depending on intent; they overlap in this case
print((b"A"*20+b"xefxbexadxde").decode('latin-1', errors='ignore'))

重要的是,请注意文字的前导b;它们在Python 2.7上被识别和忽略(除非from __future__ unicode_literals有效,在这种情况下,就像在Python 3中一样需要它们)和在Python 3上,它使文字bytes文字(没有假设特殊的编码),而不是str文字,所以你可以用你想要的编码解码。无论哪种方式,您最终都会得到原始字节,然后可以用首选编码对其进行解码,忽略错误。

请注意,忽略错误通常是错误的;你把数据放在地板上。 0xDEADBEEF不能保证在任何给定的编码中生成有用的字节字符串,如果这不是您的真实数据,您可能仍然冒着错误的风险,想要静默地忽略不可解码的数据。

如果你想写入原始字节,让任何消耗的东西stdout随心所欲地解释它们,你需要降到print级别以下,因为Python 3上的print纯粹是基于str的。要在 Python 3 上写入原始字节,您可以使用sys.stdout.buffer(sys.stdout是基于文本的,sys.stdout.buffer是它包装的底层缓冲面向字节的流);您还需要手动添加换行符(如果需要):

sys.stdout.buffer.write(b"A"*20+b"xefxbexadxden")

vs. 在 Python 2 上,stdout不是编码包装器:

sys.stdout.write(b"A"*20+b"xefxbexadxden")

对于可移植代码,您可以提前获取"原始标准输出"并使用它:

# Put this at the top of your file so you don't have to constantly recheck/reacquire
# Gets sys.stdout.buffer if it exists, sys.stdout otherwise
bstdout = getattr(sys.stdout, 'buffer', sys.stdout)
# Works on both Py2 and Py3
bstdout.write(b"A"*20+b"xefxbexadxden")

最新更新