Python是一门非常简洁的语言,对于数据类型的表示,不像其他语言预定义了许多类型(如:在C#中,光整型就定义了8种)它只定义了六种基本类型:字符串,整数,浮点数,元组(set),列表(array),字典(key/value)通过这六种数据类型,我们可以完成大部分工作。但当Python需要通过网络与其他的平台进行交互的时候,必须考虑到将这些数据类型与其他平台或语言之间的类型进行互相转换问题。
我的理解是,Python将需要与其他平台进行交互的数据全部转换为字节存储,并且同时告诉对方这些字节是怎么组合起来的,这样对方才知道如何正确的拆分这些字节流。比如下面的代码:
import struct
print
buff = struct.pack('ii',4,4); ###将两个整型数打包
str = struct.unpack('ii',buff); ###将字节流分拆为两个整型数
print (str) ###打印拆分结果为: (4, 4)
str2 = struct.unpack('q',buff); ###将字节流按照long long整型数
print (str2) ###拆分结果为:17179869188
pack方法的第一个参数为打包数据类型,也就是组合的方式,其中i
表示int整型,用四个字节表示,q
表示long long整型,用八个字节表示,所以我们按照ii
的格式(表示两个整数)解包的时候,能够正确的将八个字节的内容拆分为两个int型整数。如果将整个八字节解读为一个long long 整型,则最后的数字为17179869188。
Python还定义了其他的字符,用来表示不同的类型,如下图所示。
我们可以使用
128sl
这样的方法表示128个char型和一个long型,或者2i
表示两个int整型.
在了解上面的概念后对pack,unpack方法的使用应该没有问题了。但是有一点特别需要注意的是,在不同的系统中,某些相同的数据类型,使用了不同的字节数,这一点跟系统的编译器有光。比如下面为长整型(long int)数,在不同的操作系统和架构下占用的字节数:
操作系统 | 架构 | 大小 |
---|---|---|
Windows | IA-32 | 4 bytes |
Windows | Intel® 64 or IA-64 | 4 bytes |
Linux | IA-32 | 4 bytes |
Linux | Intel® 64 or IA-64 | 8 bytes |
Mac OS X | IA-32 | 4 bytes |
Mac OS X | Intel® 64 or IA-64 | 8 bytes |
The Intel® Compiler is compatible and inter-operable with Microsoft* Visual C++ on Windows* and with gcc* on Linux* and Mac OS X*. Consequently, the sizes of fundamental types are the same as for these compilers.
我们可以看到,long int 类型在64位Linux系统和64位Windows系统中是不同的。我们使用下面的实验来证明:
#Linux 系统(Ubuntu 16.04)中:
import struct
print struct.calcsize('l')
#输出结果为8,说明long类型,在64位Linux系统中为8字节
#Windows 系统(Windows 10)中:
import struct
print struct.calcsize('l')
#输出结果为4,说明long类型,在64位Windows系统中为4字节
为了让其在不同系统中使用相同的解释方式,我们可以使用<
来让系统采用standard而非native(native就是基于本地编译器)的方式来强制不同的系统采用相同的解释方式。
在增加了<
符号后,我们可以再次进行上面的实验。
#Linux 系统(Ubuntu 16.04)中:
import struct
print struct.calcsize('<l')
#输出结果为4
#Windows 系统(Windows 10)中:
import struct
print struct.calcsize('l')
#输出结果为4
使用非Native的方式在跨平台的时候尤其重要。