簡體   English   中英

為什么Python會自動將字符串中的十六進制編碼為UTF-8?

[英]Why does Python automatically encode hex in strings as UTF-8?

我一直在使用python進行ASCII到二進制的翻譯,並且在解析結果時一直遇到問題。 最終,我想看看Python命令正在生成什么。

在輸出中似乎插入了胭脂0xc2 (例如):

$ python -c 'print("\x80")' | xxd
00000000: c280 0a                                  ...

實際上,無論在何處使用此類字節,都會發生這種情況:

$ python -c 'print("Test\x80Test2\x81")' | xxd
00000000: 5465 7374 c280 5465 7374 32c2 810a       Test..Test2...

憑直覺,我在UTF-8旁打了一下,果然, U+0080編碼為0xc2 0x80 顯然,Python冒昧地假設\\x80實際上是U+0080的編碼。 有沒有一種方法可以更改此默認行為,或者以其他方式明確指示我打算包含單字節0x80而不是UTF編碼?

Python 3.6.2

Python 3做正確的事情是在字符串str中插入一個字符,該str是字符串而不是字節序列。

UTF8是默認編碼。 如果需要插入一個字節,則需要以該字符表示為字節的其他編碼。

$ PYTHONIOENCODING=iso-8859-1 python3 -c 'print("\x80")' | xxd
00000000: 800a

致病性編碼

如果在運行解釋器之前設置了此設置,則它將使用語法encodingname:errorhandler覆蓋用於stdin / stdout / stderr的編碼。 encodingname和:errorhandler部分都是可選的,並且與str.encode()中的含義相同。

如果要在Python 3中輸出原始字節,則不應使用print函數,因為它用於以默認編碼輸出文本。 相反,您可以使用sys.stdout.buffer.write

ASCII是7位編碼,因此,如果您的所謂ASCII包含b'\\x80'之類的字符,則不是合法的ASCII。 也許您的數據實際上是用iso-8859-1(又名latin-1)編碼的,或者可能是與Windows密切相關的變體cp1252 為了正確地執行這種操作,您需要確定用於創建數據的實際編碼。

如果要輸出"Test\\x80Test2\\x81"並使十六進制轉儲如下所示:

00000000  54 65 73 74 80 54 65 73  74 32 81                 |Test.Test2.|

你可以做

import sys
s = "Test\x80Test2\x81"
sys.stdout.buffer.write(s.encode('latin1'))

這是有效的,因為Latin-1是Unicode的子集。 這是一個快速演示:

import binascii

a = ''.join([chr(i) for i in range(256)])
b = a.encode('latin1')
print(binascii.hexlify(b))

輸出

b'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'

但是,如果您實際上是在使用二進制數據,則不應首先將其存儲在文本字符串中,而應使用bytes或可能使用bytearray 從我之前的示例中生成b字節字符串的理智方法是

b = bytes(range(256))

如果您有一個像b"Test\\x80Test2\\x81"這樣的bytes對象,則可以使用以下命令將這些字節轉儲到stdout

sys.stdout.buffer.write(b"Test\x80Test2\x81")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM