Python3以一种奇怪的方式处理非ASCII字符

时间:2019-05-16 06:05:30

标签: python python-3.x unicode ascii non-ascii-characters

我试图用Python 3解决一个可伪造的东西。为此,我需要打印一些不在ASCII范围内的字符。

Python 3正在将这些字符转换为某种奇怪的Unicode。

例如,如果我在Python 3中打印"\xff",则会得到以下信息:

root@kali:~# python3 -c 'print("\xff")' | xxd
00000000: c3bf 0a                                  ...

\xff被转换为\xc3\xbf

但是在Python 2中,它可以按预期工作,就像这样:

root@kali:~# python -c 'print("\xff")' | xxd
00000000: ff0a                                     ..

那么如何在Python 3中像这样打印呢?

2 个答案:

答案 0 :(得分:2)

在Python 2中,strbytes是同一件事,因此当您编写'\xff'时,结果包含实际的字节0xFF

在Python 3中,str更接近Python 2的unicode对象,并且不是bytes的别名。 \xff不再是一个插入字节的请求,而是一个要插入Unicode字符(其代码可以用8位表示)的请求。该字符串将使用您的默认编码(可能是UTF-8)进行打印,其中字符0xFF被编码为字节\xc3\xbf。当\x出现在字符串中时,基本上是\u的单字节版本。不过,它仍然出现在bytes中。

现在寻求解决方案。如果您只想要一些字节,请

b'\xff'

与Python 2中的工作原理相同。您可以将这些字节写入二进制文件,但是之后就不能直接打印,因为您打印的所有内容都会转换为str。打印的问题是所有内容都以文本模式进行编码。幸运的是,sys.stdout具有buffer属性,可让您直接输出bytes

sys.stdout.buffer.write(b'\xff\n')

仅当您不将sys.stdout替换为没有buffer的东西时,此方法才有效。

答案 1 :(得分:1)

在Python 2中,print '\xff'将字节字符串直接写到终端,这样您就得到了打印的字节。

在Python 3中,print('\xff')使用默认编码将Unicode字符U + 00FF编码到终端上……在您的情况下为UTF-8。

要在Python 3中直接将字节输出到终端,您不能使用print,但是可以使用以下代码跳过编码并写入字节字符串:

python3 -c "import sys; sys.stdout.buffer.write(b'\xff')"