python的struct模块

2023-11-04

  了解c语言的人,一定会知道struct结构体在c语言中的作用,它定义了一种结构,里面包含不同类型的数据(int,char,bool等等),方便对某一结构对象进行处理。而在网络通信当中,大多传递的数据是以二进制流(binary data)存在的。当传递字符串时,不必担心太多的问题,而当传递诸如int、char之类的基本数据的时候,就需要有一种机制将某些特定的结构体类型打包成二进制流的字符串然后再网络传输,而接收端也应该可以通过某种机制进行解包还原出原始的结构体数据。python中的struct模块就提供了这样的机制,该模块的主要作用就是对python基本类型值与用python字符串格式表示的C struct类型间的转化。再者, 有的时候需要用python处理二进制数据,比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用 struct来处理c语言中的结构体. struct模块中最重要的三个函数是pack(), unpack(), calcsize()


#  按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流) 

pack(fmt, v1, v2, ...) 

 # 按照给定的格式(fmt)解析字节流string,返回解析出来的tuple 

unpack(fmt, string)      

# 计算给定的格式(fmt)占用多少字节的内存 

calcsize(fmt)


struct中支持的format格式

093212_Vk5w_1458120.png

注1.q和Q只在机器支持64位操作时有意思

注2.每个格式前可以有一个数字,表示个数

注3.s格式表示一定长度的字符串,4s表示长度为4的字符串,但是p表示的是pascal字符串

注4.P用来转换一个指针,其长度和机器字长相关

注5.最后一个可以用来表示指针类型的,占4个字节

一个format字符串是用数字和上述定义的字符来表示的。如 5i 表示5个 int 型数,H 表示一个 unsigned short 类型的数, 0Q 则表示0个 unsigned long long 类型的数。在上面的表格中,如果表示了字符代表的位数,则这个字符前面再加数字,表示多个变量,如 3Q 表示3个变量;如果没有指明字符代表的位数,则前面加数据代表一个变量,如 3s 表示一个长度为3的字符串,在pack或者unpack的时候需要注意这一点。

struct支持的数据对齐方式

在与其它语言进行数据交互时,通常还要考虑的事情是:编译器是否有字节对齐?大端存储还是小端存储?在format字段串的第一个字符可以用来定义数据的对齐方式:

093408_N0vl_1458120.png

例如:

struct.unpack('>I', a)[0]  

format=">I"是什么意思,从google找了一下,有人说这个东西,可都是比较笼统,没能让我明白,于是硬着头皮看API:
By default, C numbers are represented in the machine’s native format and byte order, and properly aligned by skipping pad bytes if necessary (according to the rules used by the C compiler).
通常,C语言下数字都是机器语言的格式并且按照字节排序,同时在需要的情况下会利用跳过填补的字节来进行适当的调整

Alternatively, the first character of the format string can be used to indicate the byte order, size and alignment of the packed data。
非此即彼:字符串的第一个字符要么被用于表示字符串的字节的排序,或者是字符串的size,还有就是数据是否对准。

Native byte order is big-endian or little-endian, depending on the host system. For example, Motorola and Sun processors are big-endian; Intel and DEC processors are little-endian.
计算机的字节序要么是高位顺序,要么是低位的,这依赖于主机本身。比如,摩托罗拉和sun的处理器是高位的,但是intel和DEC的是低位的。

这样子就明白了上面的format=">I"的意思,也就是说按照高位顺序来格式化取得一个int或long值。下面问题就又来了,你怎么知道读取的就是一个int或long值呢?

通过看struct的文档,可以看到struct通过两张表制定了一定的format规则,我按照自己的观察,给他归纳为两类,一个是和C当中类型的对照,另一个就是选择按照高位还是低位来解释字节。上面已经说了高低字节顺序,那么观察和C对照的表格,发现I 代表的就是integer or long ,详细的可以去看python的API。

使用示例

示例1: C结构体打包和解包

一个C结构体:

struct Header {    
 unsigned short id;   
 char[4] tag;    
 unsigned int version;  
 unsigned int count; }

现在接收到一个上述结果体数据,可以用unpack函数解析:

import struct (id, tag, version, count) = struct.unpack('!H4s2I', s)

在上述代码中,H对应id,4s对应tag,2I对应version和count。!表示是由网络字节顺序传输。

这样,通过unpack,就解出对应的信息。同样,通过pack也可以将信息打包也对应的二进制格式:

import struct ss = struct.pack("!H4s2I", id, tag, version, count);

pack函数将信息打包成一个字符串,实际上是类C结果体字节流,表示的就是一个Header结构体。

示例2: 格式化类型和二进制的转换
import struct 
a=12.34 
#将a变为二进制 
bytes=struct.pack('i',a)

pack后,bytes就是一个str字符串,内容与a的二进制存储内容相同

可以用如下代码进行反转换:

(a,) = struct.unpack('i', bytes)

注意:unpack返回的是一个tuple。


# 使用struck.unpack获取子字符串 ,取前5个字符,跳过4个字符华,再取3个字符 
format = '5s 4x 3s'

print struct.unpack(format, 'Test astring') 
#('Test', 'ing') 

来个简单的例子吧,有一个字符串'He is not very happy',处理一下,把中间的not去掉,然后再输出。 
import struct 
theString = 'He is not very happy' 
format = '2s 1x 2s 5x 4s 1x 5s' 
print ' '.join(struct.unpack(format, theString)) 
输出结果: 
He is very happy


随后是关于网络字节的东东,从网上看来的,感觉有用:

Python的socket库采用string类型来发送和接收数据,这样当我们用
i = socket.recv(4)
来接收一个4字节的整数时,该整数实际上是以二进制的形式保存在字符串 i 的前4个字节中;大多数的时候我们需要的是一个真正的integer/long型,而不是一个用string型表示的整型。这时我们可以使用struct库:Interpret

strings as packed binary data. 对上面的情况,我们可以写
t = unpack("I", i)
第一个参数是格式化字符串,I指明字符串 i 包含的头一个数据项是一个以C语言的unsigned integer表示的整数,这里 i 只包含了一个数据项,实际上这个被解释的字符串也可以包含多个数据项,只要在格式化字符串里为每项数据指明一个格式即可;自然地,unpack返回的就是一个tuple类型了。




可能遇到的错误

1. struct.pack时可能会遇到:> struct.error: pack requires exactly 2 arguments

这一错误说明format中的参数个数与实际输入的参数个数不符。如 bytes = struct.pack('2I', a) 需要2个参数而只输入了一个

2. struct.unpack时可能会遇到:> struct.error: unpack requires a string argument of length *

这一错误说明format中参数代表的数据占用内存数,与输入的数据占用的内存长度不符。这时候可以用 struct.calcsize(fmt) 函数检查format字符代表的长度,及用len(string)函数来检测数据的长度。


转载于:https://my.oschina.net/u/1458120/blog/630744

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python的struct模块 的相关文章

  • 翠儿。让流永远运行

    我对 tweepy python 库比较陌生 我想确保我的流 python 脚本始终在远程服务器上运行 因此 如果有人能够分享如何实现这一目标的最佳实践 那就太好了 现在我正在这样做 if name main while True try
  • 没有任何元数据的 zip 文件

    我想找到一种简单的方法来压缩一堆文件 而无需任何文件元数据 例如时间戳 这zip命令似乎总是保留元数据 我没有找到禁用元数据的方法 我希望解决方案是一个命令或最多一个 python 脚本 谢谢 正如一些帖子已经指出的那样 zip 标头中的大
  • 在 Python 中使用 Selenium 处理“接受 Cookie”弹出窗口

    我一直在尝试用硒抓取这个房地产网站的一些信息 但是 当我访问该网站时 我需要接受 cookie 才能继续 这仅在机器人访问网站时发生 而不是在我手动执行时发生 当我尝试通过 xpath 或 id 查找相应的元素时 正如我在手动检查页面时找到
  • 在Python3.6中调用C#代码

    由于完全不了解 C 编码 我希望在我的 python 代码中调用 C 函数 我知道有很多关于同一问题的问答 但由于一些奇怪的原因 我无法从示例 python 模块导入简单的 c 类库 以下是我所做的事情 C 类库设置 我使用的是 VS 20
  • 如何确定非阻塞套接字是否真正连接?

    这个问题不仅限于Python 这是一个一般的套接字问题 我有一个非阻塞套接字 想要连接到一台可访问的机器 在另一端 该端口不存在 为什么 select 仍然成功 我预计会超时 sock send 因管道损坏而失败 select 之后如何确定
  • Tensorflow 可变图像输入大小(自动编码器、放大......)

    Edit WARNING不建议使用不同图像大小的图像 因为张量需要具有相同的大小才能实现并行化 我一直在寻找解决方案 了解如何使用不同大小的图像作为神经网络的输入 Numpy 第一个想法是使用numpy 然而 由于每个图像的大小不同 我无法
  • python - 是否可以扩展 xml-rpc 可以序列化的事物集?

    我看到几个问题询问如何发送numpy ndarray通过 xml rpc 调用 这不能开箱即用 因为正如 xml rpc 中所述docs https docs python org 2 library xmlrpclib html 有一组固
  • 如何从 PyCharm 项目中获取我的“exe”[重复]

    这个问题在这里已经有答案了 通过 PyCharm 在 Python 上编写一些项目 我想从中获取一个exe文件 我尝试过 另存为 gt XXX exe 但是 当我尝试执行它时出现错误 此类操作系统不支持该文件 附注 我有win7 x64 它
  • Python BeautifulSoup XML 解析

    我编写了一个简单的脚本来使用 BeautifulSoup 模块解析 XML 聊天日志 标准 soup prettify 工作正常 只是聊天日志中有很多绒毛 您可以在下面看到我正在使用的脚本代码和一些 XML 输入文件 Code import
  • 优化 Keras 以使用所有可用的 CPU 资源

    好吧 我真的不知道我在说什么 所以请耐心听我说 我正在使用 Theano 后端运行 Keras 以在 MNIST 图像上运行基本的神经网络 目前只是一个教程 过去 我一直使用我的旧 HP 笔记本电脑 因为我有 Windows 和 Ubunt
  • Paramiko - 使用私钥连接 - 不是有效的 OPENSSH 私钥/公钥文件

    我正在尝试找到解决方案 但无法理解我做错了什么 在我的 Linux 服务器上 我运行了以下命令 ssh keygen t rsa 这产生了一个id rsa and id rsa pub file 然后我将它们复制到本地并尝试运行以下代码 s
  • Python - 用逗号分割,跳过括号内的内容

    我需要用逗号分隔字符串 但我对这种情况有一个问题 TEXT EXAMPLE THIS IS A EXAMPLE BUT NOT WORKS FOR ME SECOND THIRD 我想拆分并得到 var 0 TEXT EXAMPLE THI
  • 带图像的简单 GUI [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我试图在简单的 GUI 上显示一些卡
  • 在可编辑的QSqlQueryModel中实现setEditStrategy

    这是后续这个问题 https stackoverflow com questions 49752388 editable qtableview of complex sql query 在那里 我们创建了 QSqlQueryModel 的可
  • 将 Pandas 列中的列表拆分为单独的列

    这是我在 pandas 数据框中的 特征 列 Feature Cricket 82379 Kabaddi 255 Reality 4751 Cricket 15640 Wildlife 730 LiveTV 13 Football 4129
  • Django 在选择列表更改时创建毫无意义的迁移

    我正在尝试使用可调用创建一个带有选择字段的模型 以便 Django 在选择列表更改时不会创建迁移 如中所述this https stackoverflow com questions 31788450 stop django from cr
  • 导入错误:没有名为 google.auth 的模块

    当我尝试导入时firebase admin in python 2 7我收到错误 导入错误 没有名为 google auth 的模块 这是Docker文件 https github com ammaratef45 Attendance bl
  • Python 3.2 中 **kwargs 和 dict 有什么区别?

    看起来Python的很多方面都只是功能的重复 除了我在 Python 中的 kwargs 和 dict 中看到的冗余之外 还有什么区别吗 参数解包存在差异 许多人使用kwargs 并通过dict作为论据之一 使用参数解包 Prepare f
  • 检查字符串是否只有字母和空格 - Python

    试图让 python 返回一个字符串仅包含字母和空格 string input Enter a string if all x isalpha and x isspace for x in string print Only alphabe
  • 异步和协程与任务队列

    我一直在阅读有关 python 3 中的 asyncio 模块的内容 以及更广泛地了解 python 中的协程的内容 但我不明白是什么让 asyncio 成为如此出色的工具 我的感觉是 你可以用协程做的所有事情 通过使用基于多处理模块 例如

随机推荐

  • 虚拟存储器(虚存)

    在实习面试中 面试官喜欢问一些操作系统地基础问题 忘记很多 现在只能恶补一下 段的逻辑地址形式是段号10位 段内地址20位 内存1MB 辅存10GB 那么虚拟存储器最大实际容量可能是 B 1024KB 1024MB 10GB 10GB 1M
  • Prism 框架项目应用篇 - 导航

    Prism 框架项目应用篇 导航 在Prism中 使用Navigation来进行页面之间的跳转通常需要一下几步 创建新页面 并且实现INavigationAware接口 使用IRegionManager注册页面 使用NavigationPa
  • gradle 碰到这样的问题

    gradle 碰到这样的问题 Could not HEAD https repo spring io plugins release com github librepdf openpdf 1 3 30 jaspersoft 2 openp
  • ubuntu安装mysql并远程连接

    ubuntu安装mysql并远程连接 环境 MySQL安装 连接MySQL 一些坑 环境 阿里云轻量级云服务器 ubuntu20 04 MySQL 8 0 27 0ubuntu0 20 04 1 MySQL安装 1 更新源 sudo apt
  • 把本地文件上传到git上面

    1 首先在码云上新建一个项目 记录下仓库项目地址 2 打开本地项目文件的根目录 右击选择git bash here 进入命令控制台 3 窗口输入命令 git init 初始化 会创建出一个 git文件夹 如果看不到可能隐藏 自行更改文件不可
  • 4.9 luogu_p1424

    循环取余 判定周几 include
  • 2021-06-03 类的属性操作__dict__

    1 类属性 公有的 attr 私有的 attr 类里面在定义这个属性的时候 python给它改了名字 class MyClass attr 100 公有属性 类外面可以访问 attr 200 obj MyClass print obj at
  • 有字符csv文件导入matlab_Matlab:如何读取CSV文件以及如何读取带有字符串数据项的CSV文件...

    CSV 逗号分开的文件 如果能快速的读取这些文件中的数据 无疑会帮助我们解决很多问题 1 只有数据的CSV文件 CSV file that includes only numbers As an example create a text
  • java--使用jdbcTemplate进行增删改查

    一 设置数据库连接信息 文件名 jdbc propries jdbc url jdbc mysql 10 0 2 4 63306 test1111111 useUnicode true characterEncoding utf 8 use
  • docker介绍+docker安装

    三问 为什么要用docker docker优势在哪 docker基础操作 一 docker介绍 1 容器就是一种沙盒技术 集装箱子 把应用装起来 容器的本质 进程 容器镜像就是系统里的 exe 安装包 2 docker介绍 1 docker
  • neo4j--Cypher语法练习(WITH、 FOREACH、Aggregation、UNWIND、UNION、CALL)

    1 15 WITH WITH语句将分段的查询部分连接在一起 查询结果从一部分以管道形式传递给另外一部分作为开始点 使用WITH可以在将结果传递到后续查询之前对结果进行操作 操作可以是改变结果的形式或者数量 WITH的一个常见用法就是限制传递
  • [Microsoft][SQLServer 2000 Driver for JDBC]Error establishing socket

    在通过jdbc连接SQL Server经常回出现 Microsoft SQLServer 2000 Driver for JDBC Error establishing socket 原因如下 1 通过url连接的时候指定的服务器名称或者服
  • Python 计算机视觉(十二)—— OpenCV 进行图像分割

    参考的一些文章以及论文我都会给大家分享出来 链接就贴在原文 论文我上传到资源中去 大家可以免费下载学习 如果当天资源区找不到论文 那就等等 可能正在审核 审核完后就可以下载了 大家一起学习 一起进步 加油 目录 前言 1 图像分割 2 读取
  • C++题库

    文章目录 1 求最大值 2 求圆面积 3 编写重载函数来打印字符串 4 设计带构造函数的Dog类 5 定义一个带重载构造函数的日期类 6 C 第三章 指针 动态生成Person类的对象 7 编写一个小小的计算器 能够计算两个浮点数的加 减
  • 使用Myeclipse插件将wsdl生成java客户端代码

    使用环境 MyEclipse9 0 本教程使用Myeclipse内置插件生成java代码 网上说这是xfire插件 不管怎样 生成和调用客户端代码都十分简单 1 在项目上右键 选择New gt Other gt Web Service gt
  • Mysql常用命令行

    Mysql常用命令行 第一招 mysql服务的启动和停止 net stop mysql net start mysql 第二招 登陆mysql 语法如下 mysql u用户名 p用户密码 键入命令mysql uroot p 回车后提示你输入
  • 如何用python调用webservice接口

    最近项目需要去调用其他平台接口 接口类型为webservice接口 跟经常用的http请求还不一样 然后就找到python的suds三方包 以下为根据号码查询归属地接口进行测试和举例 安装suds三方包 命令行 pip3 install s
  • VSCode 的 Local History插件使用

    VSCode 的 Local History 插件使用 在使用vscode编写代码的时候 往往需要查看历史的修改记录 这时可以安装 Local History 插件 安装成功之后 关闭 vscode 然后重新启动就可使用 在左下角可以看到
  • linux 查找安装包路径,查看yum安装软件包的路径

    Linux系统下查找安装包所在目录的方法 linux中查看软件文件安装路径 Linux查看软件安装路径 linux查找安装包路径 rpm查找安装包路径 rpm rpm qa grep php fpm rpm ql php73 php fpm
  • python的struct模块

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 了解c语言的人 一定会知道struct结构体在c语言中的作用 它定义了一种结构 里面包含不同类型的数据 int char bool等等 方便对某一结构对象进行处理 而在网络