出自:http://blog.csdn.net/oychw/article/details/8919519
2013-05-13 磁针石
#承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq 37391319 博客:http://blog.csdn.net/oychw
#版权所有,转载刊登请来函联系
#深圳测试自动化python项目接单群113938272深圳会计软件测试兼职 6089740
#深圳地摊群 66250781武冈洞口城步新宁乡情群49494279
#自动化测试和python群组:http://groups.google.com/group/automation_testing_python
#参考资料:《The PythonStandard Libraryby Example 2011》
实现字节数据和python数据类型的转换。格式指示器会有类似于re模块一样的变异机制。所以创建Struct实例,再调用实例方法会比使用模块函数更加有效。
打包和解包:
文件:struct_pack.py
import binascii
values = (1, 'ab', 2.7)
s = struct.Struct('I 2s f')
packed_data = s.pack(*values)
print 'Original values:', values
print 'Format string :', s.format
print 'Uses :', s.size, 'bytes'
print 'Packed Value :', binascii.hexlify(packed_data)
执行结果:
Original values: (1, 'ab', 2.7)
Format string : I 2s f
Uses : 12 bytes
Packed Value : 0100000061620000cdcc2c40
文件:struct_unpack.py
import struct
import binascii
packed_data =binascii.unhexlify('0100000061620000cdcc2c40')
s = struct.Struct('I 2s f')
unpacked_data = s.unpack(packed_data)
print 'Unpacked Values:', unpacked_data
执行结果:
Unpacked Values: (1, 'ab', 2.700000047683716)
import struct
import binascii
values = (1, 'ab', 2.7)
print 'Original values:', values
endianness = [
('@', 'native, native'),
('=', 'native, standard'),
('<', 'little-endian'),
('>', 'big-endian'),
('!', 'network'),
]
for code, name in endianness:
s = struct.Struct(code + ' I2s f')
packed_data = s.pack(*values)
print 'Format string :', s.format, 'for', name
print 'Uses :', s.size, 'bytes'
print 'Packed Value :', binascii.hexlify(packed_data)
print 'Unpacked Value :',s.unpack(packed_data)
执行结果:
Original values: (1, 'ab', 2.7)
Format string : @ I 2s f fornative, native
Uses : 12 bytes
Packed Value :0100000061620000cdcc2c40
Unpacked Value : (1, 'ab', 2.700000047683716)
Format string : = I 2s f fornative, standard
Uses : 10 bytes
Packed Value :010000006162cdcc2c40
Unpacked Value : (1, 'ab', 2.700000047683716)
Format string : < I 2s f forlittle-endian
Uses : 10 bytes
Packed Value :010000006162cdcc2c40
Unpacked Value : (1, 'ab', 2.700000047683716)
Format string : > I 2s f forbig-endian
Uses : 10 bytes
Packed Value :000000016162402ccccd
Unpacked Value : (1, 'ab', 2.700000047683716)
Format string : ! I 2s f fornetwork
Uses : 10 bytes
Packed Value :000000016162402ccccd
Unpacked Value : (1, 'ab', 2.700000047683716)
性能要求较高的情况下可以使用buffer,pack_into()和unpack_from()可以直接和buffer交互。
import struct
import binascii
s = struct.Struct('I 2s f')
values = (1, 'ab', 2.7)
print 'Original:', values
print 'ctypes string buffer'
import ctypes
b = ctypes.create_string_buffer(s.size)
print 'Before :',binascii.hexlify(b.raw)
s.pack_into(b, 0, *values)
print 'After :',binascii.hexlify(b.raw)
print 'Unpacked:', s.unpack_from(b, 0)
print 'array'
import array
a = array.array('c', '\0' * s.size)
print 'Before :',binascii.hexlify(a)
s.pack_into(a, 0, *values)
print 'After :',binascii.hexlify(a)
print 'Unpacked:', s.unpack_from(a, 0)
执行结果:
Original: (1, 'ab', 2.7)
ctypes string buffer
Before :000000000000000000000000
After : 0100000061620000cdcc2c40
Unpacked: (1, 'ab', 2.700000047683716)
array
Before :000000000000000000000000
After :0100000061620000cdcc2c40
Unpacked: (1, 'ab', 2.700000047683716)
Struct模块可以和namedtuple配合,使二进制数据具备更好的可读性:
>>> record = 'raymond \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb',record)
>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum schoolgradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name='raymond ',serialnum=4658, school=264, gradelevel=8)