簡體   English   中英

為什么python2和python3的print輸出同一個字符串不同?

[英]Why is the output of print in python2 and python3 different with the same string?

在python2中:

$ python2 -c 'print "\x08\x04\x87\x18"' | hexdump -C
00000000  08 04 87 18 0a                                    |.....|
00000005

在python3中:

$ python3 -c 'print("\x08\x04\x87\x18")' | hexdump -C
00000000  08 04 c2 87 18 0a                                 |......|
00000006

為什么這里有字節"\\xc2"

編輯

我認為當字符串具有非 ascii 字符時,python3 會將字節"\\xc2"附加到字符串。 (正如@Ashraful Islam 所說)

那么如何在python3中避免這種情況呢?

考慮以下代碼片段:

import sys
for i in range(128, 256):
    sys.stdout.write(chr(i))

使用 Python 2 運行它並使用hexdump -C查看結果:

00000000  80 81 82 83 84 85 86 87  88 89 8a 8b 8c 8d 8e 8f  |................|

等等。 沒有驚喜; 0x800xff 128 個字節。

用 Python 3 做同樣的事情:

00000000  c2 80 c2 81 c2 82 c2 83  c2 84 c2 85 c2 86 c2 87  |................|
...
00000070  c2 b8 c2 b9 c2 ba c2 bb  c2 bc c2 bd c2 be c2 bf  |................|
00000080  c3 80 c3 81 c3 82 c3 83  c3 84 c3 85 c3 86 c3 87  |................|
...
000000f0  c3 b8 c3 b9 c3 ba c3 bb  c3 bc c3 bd c3 be c3 bf  |................|

總結一下:

  • 一切從0x800xbf已經0xc2前綴。
  • 0xc00xff所有內容都將第 6 位設置為零,並在前面添加了0xc3

那么,這里發生了什么?

在 Python 2 中,字符串是 ASCII 並且不進行轉換。 告訴它寫一些 0-127 ASCII 范圍之外的東西,它說“oky-doke!” 並只寫入這些字節。 簡單的。

在 Python 3 中,字符串是Unicode 寫入非 ASCII 字符時,必須以某種方式對其進行編碼 默認編碼為 UTF-8。

那么,這些值是如何用 UTF-8 編碼的呢?

0x800x7ff代碼點編碼如下:

110vvvvv 10vvvvvv

其中 11 個v字符是代碼點的位。

因此:

0x80                 hex
1000 0000            8-bit binary
000 1000 0000        11-bit binary
00010 000000         divide into vvvvv vvvvvv
11000010 10000000    resulting UTF-8 octets in binary
0xc2 0x80            resulting UTF-8 octets in hex

0xc0                 hex
1100 0000            8-bit binary
000 1100 0000        11-bit binary
00011 000000         divide into vvvvv vvvvvv
11000011 10000000    resulting UTF-8 octets in binary
0xc3 0x80            resulting UTF-8 octets in hex

所以這就是你在87之前獲得c2的原因。

如何在 Python 3 中避免這一切? 使用bytes類型。

Python 2 的默認字符串類型是字節字符串。 字節字符串寫為"abc"而 Unicode 字符串寫為u"abc"

Python 3 的默認字符串類型是 Unicode 字符串。 字節字符串寫為b"abc"而 Unicode 字符串寫為"abc"u"abc"仍然有效)。 由於有數百萬個 Unicode 字符,將它們打印為字節需要一種編碼(在您的情況下為UTF-8 ),每個代碼點需要多個字節。

首先在 Python 3 中使用字節字符串來獲取與 Python 2 相同的類型。 然后,因為 Python 3 的print需要 Unicode 字符串,所以使用sys.stdout.buffer.write寫入原始 stdout 接口,它需要字節字符串。

python3 -c 'import sys; sys.stdout.buffer.write(b"\x08\x04\x87\x18")'

請注意,如果寫入文件,則存在類似問題。 對於無編碼轉換,以二進制模式'wb'打開文件並寫入字節字符串。

暫無
暫無

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

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