2016-10-03 546 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(),用于较短的代码。