为什么打印这些\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")