设为首页 收藏本站
查看: 940|回复: 0

[经验分享] python struct 学习笔记

[复制链接]

尚未签到

发表于 2017-4-27 11:18:27 | 显示全部楼层 |阅读模式
python struct 学习笔记

part 1: introduce

python 是一门简洁的语言。为了与其他语言或平台(尤其在网络传输过程中)进行互相转换,有必要了解一下 python struct.

  part 2: get help
NAME
struct
FILE
/usr/lib/python2.6/struct.py
FUNCTIONS
calcsize(...)
Return size of C struct described by format string fmt.
pack(...)
Return string containing values v1, v2, ... packed according to fmt.
pack_into(...)
Pack the values v1, v2, ... according to fmt.
Write the packed bytes into the writable buffer buf starting at offset.
unpack(...)
Unpack the string containing packed C structure data, according to fmt.
Requires len(string) == calcsize(fmt).
unpack_from(...)
Unpack the buffer, containing packed C structure data, according to
fmt, starting at offset. Requires len(buffer[offset:]) >= calcsize(fmt).


part 3: instances

function 1:
calcsize(...) 计算格式字符串对应的结果的长度

>>> b = struct.calcsize('HB')
>>> b
3
>>> b = struct.calcsize('!HBBBBBBIIIIBH')
>>> b
27
>>> b = struct.calcsize('HBBBBBBIIIIBH')
>>> b
28

function 2:
pack(...) 根据格式字符串,将python值转换为字节流(字节数组)

>>> a = struct.pack("!HBBBBBBIIIIBH",48251,0,24,0,1,0,0,842003,4294963512,2300851747,368142189,1,2)
>>> a
'\xbc{\x00\x18\x00\x01\x00\x00\x00\x0c\xd9\x13\xff\xff\xf18\x89$6#\x15\xf1gm\x01\x00\>>> repr(a)x02'

function 3:
pack_into(...) 与pack()类似。根据格式字符串,将python值转换为字节流(字节数组),并且将这字节流保存到一个buffer 中

>>> from ctypes import create_string_buffer
>>> buf = create_string_buffer(40)
>>> a = struct.pack_into("!HBBBBBBIIIIBH",buf,0,48251,0,24,0,1,0,0,842003,4294963512,2300851747,368142189,1,2)
>>> buf
<ctypes.c_char_Array_40 object at 0x7f0eefd11dd0>

function 4:
unpack(...) 与pack() 相反。根据格式字符串,将字节流转换成python 数据类型。
  >>> b = struct.unpack("!HBBBBBBIIIIBH",a)
>>> b
(48251, 0, 24, 0, 1, 0, 0, 842003, 4294963512, 2300851747, 368142189, 1, 2)


function 5:
unpack_from(...) 与unpack()类似。根据格式字符串,从一个buffer 中将字节流转换成python 数据类型

>>> b = struct.unpack_from("!HBBBBBBIIIIBH",buf,0)
>>> b
(48251, 0, 24, 0, 1, 0, 0, 842003, 4294963512, 2300851747, 368142189, 1, 2)
>>> buf
  <ctypes.c_char_Array_40 object at 0x7f0eefd11dd0>
  

  # pack 之后得到的字节流(数组)也可以像序列一样来操作:
>>> a = struct.pack("!HBBBBBBIIIIBH",48251,0,24,0,1,0,0,842003,4294963512,2300851747,368142189,1,2)
>>> a
'\xbc{\x00\x18\x00\x01\x00\x00\x00\x0c\xd9\x13\xff\xff\xf18\x89$6#\x15\xf1gm\x01\x00\x02'
>>> len(a)
27
>>> head = a[:25]
>>> head
'\xbc{\x00\x18\x00\x01\x00\x00\x00\x0c\xd9\x13\xff\xff\xf18\x89$6#\x15\xf1gm\x01'
>>> command = a[25:]
>>> command
'\x00\x02'
>>> command = a[24:]
>>> command
'\x01\x00\x02'
>>> command = a[-4:]
>>> command
'm\x01\x00\x02'
>>> command = a[-3:]
>>> command
'\x01\x00\x02'

part 4: big-endian & format

Functions to convert between Python values and C structs represented
as Python strings. It uses format strings (explained below) as compact
descriptions of the lay-out of the C structs and the intended conversion
to/from Python values.

The optional first format char indicates byte order, size and alignment:
@: native order, size & alignment (default)
=: native order, std. size & alignment
<: little-endian, std. size & alignment
>: big-endian, std. size & alignment
!: same as >

The remaining chars indicate types of args and must match exactly;
these can be preceded by a decimal repeat count:
x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;
?: _Bool (requires C99; if not available, char is used instead)
h:short; H:unsigned short; i:int; I:unsigned int;
l:long; L:unsigned long; f:float; d:double.
Special cases (preceding decimal count indicates length):
s:string (array of char); p: pascal string (with count byte).
Special case (only available in native format):
P:an integer type that is wide enough to hold a pointer.
Special case (not in native mode unless 'long long' in platform C):
q:long long; Q:unsigned long long
Whitespace between formats is ignored.

大端模式:

字节的传输约定:按照B7~B0的顺序传输;
字的传输约定: 先传递高8位(B15~B8),再传递低8位,(B7~B0);
双字的传输约定: 先传递高24位,(B31~B24),然后传递高16位(B23~B16),再传递高8位(B15~B8),最后传递低8位(B7~B0)。

>>> b = struct.pack("!H",1)
>>> b
'\x00\x01'
>>> b = struct.pack("H",1)
>>> b
'\x01\x00'
>>> b = struct.pack("L",1)
>>> b
'\x01\x00\x00\x00\x00\x00\x00\x00'
>>> b = struct.pack("!L",1)
>>> b
'\x00\x00\x00\x01'


格式化字符串:

# P   void *   long
>>> buffer = struct.pack("P",1)
>>> buffer
'\x01\x00\x00\x00\x00\x00\x00\x00'

# p   char[]   string
>>> buffer = struct.pack("p","string")
>>> buffer
'\x00'

# s   char[]   string
>>> buffer = struct.pack("ssss","string")
>>> buffer
's'
>>> buffer = struct.pack("sss","string","st","ff")
>>> buffer
'ssf'
>>> buffer = struct.pack("sss","string","j","ff")
>>> buffer
'sjf'
>>> buffer = struct.pack("%ds"%len('jia xiaolei'),"jia xiaolei")
>>> buffer
'jia xiaolei'

# d   double   float
>>> buffer = struct.pack("d", 1.2)
>>> buffer
'333333\xf3?'

# f   float   float
>>> buffer = struct.pack("f", 1.2)
>>> buffer
'\x9a\x99\x99?'

# 这里很有用,Q 可以匹配几乎所有的东西
Q   unsigned long long   long
>>> buffer = struct.pack("Q",25111)
>>> buffer
'\x17b\x00\x00\x00\x00\x00\x00'
>>> buffer = struct.pack("Q",47882545111)
>>> buffer
'\xd7\xa7\x05&\x0b\x00\x00\x00'

# q   long long   long
>>> buffer = struct.pack("q",47882545111)
>>> buffer
'\xd7\xa7\x05&\x0b\x00\x00\x00'
>>> buffer = struct.pack("q",2545111)
>>> buffer
'\xd7\xd5&\x00\x00\x00\x00\x00'
  

  # L   unsigned long   long
>>> buffer = struct.pack("L",2545111)
>>> buffer
'\xd7\xd5&\x00\x00\x00\x00\x00'
>>> buffer = struct.pack("L",47882545111)
>>> buffer
'\xd7\xa7\x05&\x0b\x00\x00\x00'

# l   long   integer
>>> buffer = struct.pack("l",47882545111)
>>> buffer
'\xd7\xa7\x05&\x0b\x00\x00\x00'
>>> buffer = struct.pack("l",2545111)
>>> buffer
'\xd7\xd5&\x00\x00\x00\x00\x00'
>>> buffer = struct.pack("l",47882545111)
>>> buffer
'\xd7\xa7\x05&\x0b\x00\x00\x00'
>>> buffer = struct.pack("l",2545111)
>>> buffer
'\xd7\xd5&\x00\x00\x00\x00\x00'
  

  # I   unsigned int   integer or long
>>> buffer = struct.pack("I",2545111)
>>> buffer
'\xd7\xd5&\x00'
>>> buffer = struct.pack("I",47882545111)
__main__:1: DeprecationWarning: 'I' format requires 0 <= number <= 4294967295
# 如果传入的值的范围查过格式字符串说约定的范围,会报错

# i   int   integer
>>> buffer = struct.pack("i",5111)
>>> buffer
'\xf7\x13\x00\x00'
>>> buffer = struct.pack("i",775111)
>>> buffer
'\xc7\xd3\x0b\x00'

# H   unsigned short   integer
>>> buffer = struct.pack("H",775111)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
struct.error: ushort format requires 0 <= number <= USHRT_MAX
>>> buffer = struct.pack("H",11)
>>> buffer
'\x0b\x00'
>>> buffer = struct.pack("H",711)
>>> buffer
'\xc7\x02'

# h   short   integer
>>> buffer = struct.pack("h",711)
>>> buffer
'\xc7\x02'
>>> buffer = struct.pack("",7811)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
struct.error: pack requires exactly 0 arguments

# ?   _Bool   bool
>>> buffer = struct.pack("?",True)
>>> buffer
'\x01'
>>> buffer = struct.pack("?",False)
>>> buffer
'\x00'

# B   unsigned char   integer
>>> buffer = struct.pack("B",2)
>>> buffer
'\x02'
>>> buffer = struct.pack("B",15)
>>> buffer
'\x0f'

# b   signed char   integer
>>> buffer = struct.pack("b",15)
>>> buffer
'\x0f'
>>> buffer = struct.pack("b",1)
>>> buffer
'\x01'
>>> buffer = struct.pack("b",51)
>>> buffer
'3'
>>> buffer = struct.pack("b",51)
>>> buffer
'3'

# c   char   string of length 1
>>> buffer = struct.pack("c","1")
>>> buffer
'1'
>>> buffer = struct.pack("c","7")
>>> buffer
'7'

# x
>>> buffer = struct.pack("x",)
>>> buffer
'\x00'

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-369928-1-1.html 上篇帖子: python异常处理常见错误 下篇帖子: Python学习之一 控制流初步
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表