2016-10-03 544 views
1

我實際上想知道python3的struct.pack行爲,但也許我錯過了一些東西。python3 struct.pack字符串作爲參數

我正在通過UDP提交一個.jpg文件。 Btw:當我嘗試一次提交整個文件(〜200kB)時,socket.sendTo()sendAll()函數會拋出「Python IOError:[Errno 90] Message too long」。所以我提交了1024字節的文件。沒有問題,我只是想知道爲什麼我發現沒有什麼關於這個大小限制在python文檔。

無論如何,我的主要問題是:我需要struct.pack來在每個片段的開頭放置一些信息 - > 2個固定大小的字符串。

但是當我做

chunk = struct.pack("!3c4cI", bytes("JPG", "utf-8"), bytes(dev_id, "utf-8"), i) 

它去 「struct.error:包裝預期中的8項包裝(有3)」

,所以我必須去

chunk = struct.pack("!3c4ci", b"J", b"P", b"G", 
    bytes(dev_id[0:1], "utf-8"), 
    bytes(dev_id[1:2], "utf-8"), 
    bytes(dev_id[2:3], "utf-8"), 
    bytes(dev_id[3:4], "utf-8"), i) 

到讓它起作用。這是爲什麼!?

回答

1

struct.pack要求每個項目作爲單獨的參數傳遞。另外的Python使得charbyte之間的區別,儘管用C它們是同義詞,這就是爲什麼你需要有一個字節bytes值的c,而不是在範圍0的整數.. 255

然而,struct還支持s格式說明,其中s代表給定長度的字符串:

>>> dev_id, i = 'R2D2', 42 
>>> struct.pack("!3s4sI", b"JPG", dev_id.encode(), i) 
b'JPGR2D2\x00\x00\x00*' 

或者,如果你正在使用至少Python的3.5,然後感謝PEP 448 -- Additional Unpacking Generalizations您可以結合使用B(無符號字節)格式的圖示操作*這樣的:

>>> struct.pack("!3B4BI", *b"JPG", *dev_id.encode(), i) 

什麼*在這裏所做的是從給定的bytes值的每一個字節解壓作爲內的整範圍0 ... 255分成不同的參數;如果dev_id.encode()導致4個UTF-8字節,則總共8個參數將傳遞到struct.pack。與c不同,B接受單個字節值作爲整數。


P.S.請注意,我直接使用b'JPG'而不是調用bytes('JPG', 'UTF-8'),並且在默認情況下對UTF-8編碼的字符串同樣也稱爲.encode(),用於較短的代碼。