Python标准库笔记struct模块的使用
作者:j_hao104 发布时间:2024-01-01 14:21:45
最近在学习python网络编程这一块,在写简单的socket通信代码时,遇到了struct这个模块的使用,当时不太清楚这到底有和作用,后来查阅了相关资料大概了解了,在这里做一下简单的总结。
了解c语言的人,一定会知道struct结构体在c语言中的作用,它定义了一种结构,里面包含不同类型的数据(int,char,bool等等),方便对某一结构对象进行处理。而在网络通信当中,大多传递的数据是以二进制流(binary data)存在的。当传递字符串时,不必担心太多的问题,而当传递诸如int、char之类的基本数据的时候,就需要有一种机制将某些特定的结构体类型打包成二进制流的字符串然后再网络传输,而接收端也应该可以通过某种机制进行解包还原出原始的结构体数据。python中的struct模块就提供了这样的机制,该模块的主要作用就是对python基本类型值与用python字符串格式表示的C struct类型间的转化(This module performs conversions between Python values and C structs represented as Python strings.)。stuct模块提供了很简单的几个函数,下面写几个例子。
该模块作用是完成Python数值和C语言结构体的Python字符串形式间的转换。这可以用于处理存储在文件中或从网络连接中存储的二进制数据,以及其他数据源。
用途: 在Python基本数据类型和二进制数据之间进行转换
struct模块提供了用于在字节字符串和Python原生数据类型之间转换函数,比如数字和字符串。
模块函数和Struct类
它除了提供一个Struct类之外,还有许多模块级的函数用于处理结构化的值。这里有个格式符(Format specifiers)的概念,是指从字符串格式转换为已编译的表示形式,类似于正则表达式的处理方式。通常实例化Struct类,调用类方法来完成转换,比直接调用模块函数有效的多。下面的例子都是使用Struct类。
Packing(打包)和Unpacking(解包)
Struct支持将数据packing(打包)成字符串,并能从字符串中逆向unpacking(解压)出数据。
在本例中,格式指定器(specifier)需要一个整型或长整型,一个两个字节的string,和一个浮点数。格式符中的空格用于分隔各个指示器(indicators),在编译格式时会被忽略。
import struct
import binascii
values = (1, 'ab'.encode('utf-8'), 2.7)
s = struct.Struct('I 2s f')
packed_data = s.pack(*values)
print('原始值:', values)
print('格式符:', s.format)
print('占用字节:', s.size)
print('打包结果:', binascii.hexlify(packed_data))
# output
原始值: (1, b'ab', 2.7)
格式符: b'I 2s f'
占用字节: 12
打包结果: b'0100000061620000cdcc2c40'
这个示例将打包的值转换为十六进制字节序列,用binascii.hexlify()方法打印出来。
使用unpack()方法解包。
import struct
import binascii
packed_data = binascii.unhexlify(b'0100000061620000cdcc2c40')
s = struct.Struct('I 2s f')
unpacked_data = s.unpack(packed_data)
print('解包结果:', unpacked_data)
# output
解包结果: (1, b'ab', 2.700000047683716)
将打包的值传给unpack(),基本上返回相同的值(浮点数会有差异)。
字节顺序/大小/对齐
默认情况下,pack是使用本地C库的字节顺序来编码的。格式化字符串的第一个字符可以用来表示填充数据的字节顺序、大小和对齐方式,如下表所描述的:
Character | Byte order | Size | Alignment |
---|---|---|---|
@ | 本地 | 本地 | 本地 |
= | 本地 | standard | none |
< | little-endian(小字节序) | standard | none |
> | big-endian(大字节序) | standard | none |
! | network (= big-endian) | standard | none |
如果格式符中没有设置这些,那么默认将使用 @。
本地字节顺序是指字节顺序是由当前主机系统决定。比如:Intel x86和AMD64(x86-64)使用小字节序; Motorola 68000和 PowerPC G5使用大字节序。ARM和Intel安腾支持切换字节序。可以使用sys.byteorder查看当前系统的字节顺序。
本地大小(Size)和对齐(Alignment)是由c编译器的sizeof表达式确定的。它与本地字节顺序对应。
标准大小由格式符确定,下面会讲各个格式的标准大小。
示例:
import struct
import binascii
values = (1, 'ab'.encode('utf-8'), 2.7)
print('原始值 : ', values)
endianness = [
('@', 'native, native'),
('=', 'native, standard'),
('<', 'little-endian'),
('>', 'big-endian'),
('!', 'network'),
]
for code, name in endianness:
s = struct.Struct(code + ' I 2s f')
packed_data = s.pack(*values)
print()
print('格式符 : ', s.format, 'for', name)
print('占用字节: ', s.size)
print('打包结果: ', binascii.hexlify(packed_data))
print('解包结果: ', s.unpack(packed_data))
# output
原始值 : (1, b'ab', 2.7)格式符 : b'@ I 2s f' for native, native
占用字节: 12
打包结果: b'0100000061620000cdcc2c40'
解包结果: (1, b'ab', 2.700000047683716)格式符 : b'= I 2s f' for native, standard
占用字节: 10
打包结果: b'010000006162cdcc2c40'
解包结果: (1, b'ab', 2.700000047683716)格式符 : b'< I 2s f' for little-endian
占用字节: 10
打包结果: b'010000006162cdcc2c40'
解包结果: (1, b'ab', 2.700000047683716)格式符 : b'> I 2s f' for big-endian
占用字节: 10
打包结果: b'000000016162402ccccd'
解包结果: (1, b'ab', 2.700000047683716)格式符 : b'! I 2s f' for network
占用字节: 10
打包结果: b'000000016162402ccccd'
解包结果: (1, b'ab', 2.700000047683716)
格式符
格式符对照表如下:
Format | C Type | Python type | Standard size | Notes |
---|---|---|---|---|
x | pad byte | no value | ||
c | char | bytes of length 1 | 1 | |
b | signed char | integer | 1 | (1),(3) |
B | unsigned char | integer | 1 | (3) |
? | _Bool | bool | 1 | (1) |
h | short | integer | 2 | (3) |
H | unsigned short | integer | 2 | (3) |
i | int | integer | 4 | (3) |
I | unsigned int | integer | 4 | (3) |
l | long | integer | 4 | (3) |
L | unsigned long | integer | 4 | (3) |
q | long long | integer | 8 | (2), (3) |
Q | unsigned long long | integer | 8 | (2), (3) |
n | ssize_t | integer | (4) | |
N | size_t | integer | (4) | |
f | float | float | 4 | (5) |
d | double | float | 8 | (5) |
s | char[] | bytes | ||
p | char[] | bytes | ||
P | void * | integer | (6) |
缓冲区
将数据打包成二进制通常是用在对性能要求很高的场景。
在这类场景中可以通过避免为每个打包结构分配新缓冲区的开销来优化。
pack_into()和unpack_from()方法支持直接写入预先分配的缓冲区。
import array
import binascii
import ctypes
import struct
s = struct.Struct('I 2s f')
values = (1, 'ab'.encode('utf-8'), 2.7)
print('原始值:', values)
print()
print('使用ctypes模块string buffer')
b = ctypes.create_string_buffer(s.size)
print('原始buffer :', binascii.hexlify(b.raw))
s.pack_into(b, 0, *values)
print('打包结果写入 :', binascii.hexlify(b.raw))
print('解包 :', s.unpack_from(b, 0))
print()
print('使用array模块')
a = array.array('b', b'\0' * s.size)
print('原始值 :', binascii.hexlify(a))
s.pack_into(a, 0, *values)
print('打包写入 :', binascii.hexlify(a))
print('解包 :', s.unpack_from(a, 0))
# output
原始值: (1, b'ab', 2.7)使用ctypes模块string buffer
原始buffer : b'000000000000000000000000'
打包结果写入 : b'0100000061620000cdcc2c40'
解包 : (1, b'ab', 2.700000047683716)使用array模块
原始值 : b'000000000000000000000000'
打包写入 : b'0100000061620000cdcc2c40'
解包 : (1, b'ab', 2.700000047683716)
来源:http://www.cnblogs.com/jhao/p/8458029.html
猜你喜欢
- 思路:创建文件时,先检查是否有同名文件(使用os.path.isfile),如果有,则在文件名后加上编号n来创建。关键点:1. 使用os.p
- 同时在线访问量继续增大 对于1G内存的服务器明显感觉到吃力严重时甚至每天都会死机 或者时不时的服务器卡一下 这个问题曾经困扰了我半个多月My
- 套接字socket套接字(socket)是计算机之间进行通信的一种技术,它允许不同主机上的进程之间进行数据交换。在Python中,我们可以使
- os.path模块是os模块根据系统类型从另一个模块导入的,并非由os模块实现1、os.path.abspath(相对路径)-----返回对
- 本文实例讲述了Sql Server事务语法及使用方法。分享给大家供大家参考,具体如下:事务是关于原子性的。原子性的概念是指可以把一些事情当做
- 前言reinhard算法:Color Transfer between Images,作者Erik Reinhardwelsh算法:Tran
- 前言:Python函数之所以很好用,还有一点就的能传递参数实现不同场景的灵活使用,对于函数参数的类型小编总结了6种不同的形式。下面来一一学习
- 1、使用基础Python代码来读写和处理CSV文件import sys#使用基础Python代码来读写和处理CSV文件input_file
- 代码如下import pandas as pdimport matplotlib.pyplot as pltimport numpy as
- 一、项目说明在日常生活中,我们经常会存取一些朋友们的丑照,在这个项目中,我们以萌萌哒的熊猫头作为背景,然后试着在背景图上加入朋友们的照片。效
- pandas.DataFrame为每一列保存一个数据类型dtype。要仅提取(选择)特定数据类型为dtype的列,请使用pandas.Dat
- 这篇文章中的内容是来源于去年我用美国的VPS搭建博客的初始阶段,那是有很多恶意访问,我就根据access log中的源IP来进行了很多统计,
- Tkinter是python的GUI模块,内含各种窗口控件,利用其中messagbox可以制作各种信息弹出窗口。以下是制作信息提示框的代码:
- 昨天正当我用十成一阳指功力戳键盘、昏天暗地coding的时候,正好被人问了一个问题,差点没收好功,洪荒之力侧漏震伤桌边的人,废话不多说,先上
- 1.python版本与matlab版本的对应关系在MAC中安装了Anaconda3,其中自带的python版本为3.8,通过python版本
- 1.mysql中or语法的使用,在mysql语法中or使用注意点。 项目遇到坑,遍历发放奖励数据查询错误!!!$sql = 'SEL
- 修改配置文件:vim /usr/local/php/etc/php.ini[Phar]phar.readonly = Off压缩:a. 创建
- 没办法,自己看看吧。 CSDN 的代码高亮用的是一个 jquery 扩展。因为我基本上只贴 java 代码,所以把当中有用的提取出来,把这段
- 后来看到博客园在用NorthScale Memcached Server(官方站点:http://www.couchbase.com/pro
- 本文实例为大家分享了python实现Nao机器人单目测距的具体代码,供大家参考,具体内容如下此代码适于用做对Nao机器人做视觉识