Python 通过 python-snap7 读写西门子 S7-300/400 PLC 实战指南
简介这份资源面向需要用 Python 与西门子 S7-300、S7-400 系列 PLC 通信的工程师与学习者通过 TCP/IP 直连方式实现数据读写省去依赖专用组态软件的麻烦。压缩包共 12 个文件约 910KB包含 3 个 py 脚本与 2 个 pyc 编译文件承载通信与业务逻辑5 个 xls 用于 PLC 点位标签与校验数据管理另有 1 个 ui 界面文件和 1 个 png 示意图整体结构紧凑。作者已亲测跑通并附上自制的 DEMO 工程其中演示了 Python 对 Excel 文件的读写处理界面用 QT 简单搭建方便对照理解通信流程与数据落盘方式。目前已有 3616 人学习下载适合希望快速上手西门子 PLC 数据采集、点位表管理与上位机交互的读者参考借鉴。1. 用 Python 打通西门子 S7-300/400为什么我最后选了 python-snap7车间里那台跑了七八年的 S7-300 还在稳定干活但上位机那边要加个数据看板或者把产量、报警记录导进 Excel 做日报找原厂改一次程序报价够买台新电脑。这种场景下用 Python 直接读写 PLC 的 DB 块、M 区、I/Q 区是最省事的路径。我试过 OPC 服务器转一道、也试过组态软件脚本最后稳定跑下来的还是 python-snap7 这条路——它直接封装了西门子 S7 通信协议基于 ISO-TCP 的 RFC1006不依赖西门子官方驱动Windows、Linux、树莓派都能装。这篇笔记面向的是手上有 S7-300 或 S7-400、想用 Python 做数据采集或轻量控制的工程师。S7-1200/1500 也能连但需要额外开启访问权限本文重点放在 300/400 这两个老系列上因为它们的坑更集中、资料更零散。读完你能自己搭起连接、读写 DB 块、把数据落进 Excel并且知道连不上时该查哪几个地方。2. 环境搭建与连接参数从装包到第一次握手2.1 python-snap7 的安装与那个绕不开的 DLLpython-snap7 本身是纯 Python 封装但它底层调用的是 snap7 的 C 库snap7.dll / libsnap7.so。很多人pip install python-snap7之后一运行就报RuntimeError: cant find snap7 library就是这一步没处理。Windows 下的常见做法是去 snap7 官方源下载对应版本的压缩包把snap7.dll放到C:\Windows\System32或者 Python 安装目录的DLLs文件夹里。Linux 下更省事直接装系统包# Ubuntu/Debian 系 sudo apt-get install snap7 # 或者用 pip 装完 python 包后手动把 libsnap7.so 放到 /usr/lib/ pip install python-snap7装完先验证库能不能加载这一步能省掉后面一半的玄学问题import snap7 from snap7.util import * # 打印 snap7 底层库版本能打印出来说明 DLL/SO 加载成功 print(snap7.__version__) client snap7.client.Client() print(Client 对象创建成功)逻辑说明snap7.client.Client()是所有操作的入口对象创建它本身不建立网络连接只是初始化。如果这一行就报错问题一定在库文件路径不在网络。参数上没什么可调的重点是把库文件放对位置。2.2 连接 S7-300/400 的四个关键参数连接 PLC 用的是client.connect(address, rack, slot, tcpport)四个参数里前三个最容易填错。import snap7 client snap7.client.Client() # 典型 S7-300/400 连接参数 # address: PLC 的 IP # rack: 机架号S7-300/400 通常是 0 # slot: 槽号S7-300 的 CPU 一般在 2S7-400 视电源和接口模块位置而定 # tcpport: ISO-TCP 端口默认 102 client.connect(192.168.0.10, 0, 2, 102) # 确认连接状态 print(client.get_connected()) # True 表示握手成功 # 读一下 CPU 信息验证通信正常 cpu_info client.get_cpu_info() print(cpu_info.ModuleTypeName)逻辑说明rack和slot是 S7 协议里定位 CPU 的坐标。S7-300 一般是 rack0、slot2S7-400 如果机架上先插了电源模块和接口模块CPU 的 slot 可能是 2 或 3得看硬件组态。tcpport默认 102除非网络管理员改过否则不用动。参数怎么改连不上时先把slot在 2 和 3 之间试一遍这是最常见的翻车点。另外确认 PLC 的 IP 和电脑在同一网段用ping先通一下。S7-300 老 CPU 有的不支持 ISO-TCP需要确认 CPU 型号带 PN 或已配 CP343-1 以太网模块。提示连接前先在 STEP7 或博途的硬件组态里确认 CPU 的以太网接口已启用并且没有勾选禁止来自远端的通信之类的保护选项。3. 读写 DB 块与 M 区地址换算和数据类型处理3.1 DB 块读取从字节流到真实数值PLC 里的数据是一段连续的字节Python 拿到的是bytearray需要按数据类型解析。这是整个流程里最需要细心的地方偏移量算错一位读出来的数就是乱的。import snap7 from snap7.util import get_real, get_int, get_bool client snap7.client.Client() client.connect(192.168.0.10, 0, 2, 102) # 读取 DB1从偏移 0 开始读 12 个字节 # db_read(db_number, start, size) data client.db_read(1, 0, 12) # 按偏移解析假设 DB1.DBD0 是 RealDB1.DBW4 是 IntDB1.DBX6.0 是 Bool temperature get_real(data, 0) # 偏移 04 字节 Real count get_int(data, 4) # 偏移 42 字节 Int running get_bool(data, 6, 0) # 偏移 6第 0 位 Bool print(f温度{temperature}, 计数{count}, 运行{running})逻辑说明db_read的start是字节偏移size是要读的字节数。get_real、get_int、get_bool这些工具函数负责把字节流按西门子的字节序大端解析成 Python 值。注意get_bool多一个 bit 参数因为布尔量是按位寻址的。参数怎么改偏移量必须和 PLC 程序里的变量地址严格对应。DB1.DBD0 对应偏移 0DB1.DBD4 对应偏移 4以此类推。如果一次读多个不连续的变量要么分多次读要么一次读一大段再按偏移切。读的 size 别超过 DB 块实际长度否则会报错。3.2 写入与 M 区、I/Q 区操作写操作和读对称用db_write。M 区标志位、I 区输入、Q 区输出用另外的接口。from snap7.util import set_real, set_int # 写 DB1.DBD8 一个 Real 值 write_buf bytearray(4) set_real(write_buf, 0, 25.6) client.db_write(1, 8, write_buf) # 读 M 区从 MB0 开始读 4 个字节 m_data client.read_area(snap7.types.Areas.MK, 0, 0, 4) # 读 Q 区从 QB0 开始读 2 个字节 q_data client.read_area(snap7.types.Areas.PA, 0, 0, 2) # 读 I 区从 IB0 开始读 2 个字节 i_data client.read_area(snap7.types.Areas.PE, 0, 0, 2)逻辑说明read_area的第一个参数是区域代码Areas.MK是 M 区Areas.PA是输出区QAreas.PE是输入区IAreas.DB是数据块。第二个参数是 DB 号非 DB 区填 0第三个是起始字节第四个是长度。参数怎么改写 DB 时db_write的start同样是字节偏移写入的bytearray长度要和数据类型匹配——Real 是 4 字节Int 是 2 字节。写 M 区用write_area区域代码用Areas.MK。注意写 Q 区会直接影响现场输出调试阶段务必先确认没有接实际执行机构或者用仿真环境。注意对运行中的产线 PLC 做写操作前一定确认目标地址不是安全联锁或急停相关的变量。我一般先在离线环境把地址表核对三遍再上现场。3.3 把采集数据落进 Excel采集回来的数据最终要给人看Excel 是最通用的载体。用 openpyxl 或 pandas 都行我一般用 pandas 直接写代码短。import pandas as pd from datetime import datetime records [] for i in range(10): data client.db_read(1, 0, 12) records.append({ 时间: datetime.now().strftime(%Y-%m-%d %H:%M:%S), 温度: get_real(data, 0), 计数: get_int(data, 4), 运行: get_bool(data, 6, 0), }) time.sleep(1) df pd.DataFrame(records) df.to_excel(plc_data.xlsx, indexFalse)逻辑说明循环采集时每次重新db_read把解析后的值存进字典列表最后一次性写 Excel。to_excel的indexFalse去掉行号列表格更干净。参数怎么改采集周期用time.sleep控制但注意别设太短S7-300 的通信资源有限100ms 以下的高频采集容易丢包。数据量大时建议先写 CSV最后再转 Excel避免内存里堆太多 DataFrame。4. 避坑与排查连不上、读出错、写不进的五条血泪经验4.1 现象connect 超时ping 得通但连不上原因最常见的是 rack/slot 填错其次是 PLC 的 ISO-TCP 端口被防火墙挡了或者 CPU 本身不支持以太网通信老款 S7-300 只有 MPI 口必须加 CP343-1 模块。解决先用 STEP7 在线看硬件组态确认 rack/slot用telnet 192.168.0.10 102测端口通不通确认 CPU 型号带 PN 或已装以太网 CP 模块。三条都过了还连不上换根网线试试我遇到过网线水晶头氧化导致间歇性断连的。4.2 现象db_read 报 Address out of range原因读的起始偏移加长度超过了 DB 块的实际定义长度。比如 DB1 只定义了 10 个字节你从偏移 8 读 4 个字节就越界了。解决在 STEP7 里打开 DB 块看实际长度或者用client.db_get(1)拿到 DB 信息里的 Size 字段。读之前先判断start size db_size。4.3 现象读出来的 Real 值是个天文数字或极小值原因字节序搞反了或者偏移量差了一位。西门子是大端序python-snap7 的get_real已经处理了大端但如果偏移量错了解析出来的就是相邻变量的字节。解决对照 PLC 变量表逐个核对偏移。DB1.DBD0 是偏移 0DB1.DBD4 是偏移 4别把 DBD 的编号当成偏移量。用get_real读出来不对时先print(data.hex())看原始字节手动算一下。4.4 现象db_write 返回成功但 PLC 里值没变原因写到了错误的 DB 号或偏移或者 PLC 程序在下一个扫描周期把该地址覆盖了。还有一种情况是 DB 块被设置为只读或处于优化访问模式S7-1200/1500 常见。解决确认 DB 号和偏移无误检查 PLC 程序里是否有对该地址的写操作S7-300/400 的 DB 块默认是非优化访问一般不存在这个问题但如果是从 1200/1500 移植过来的程序要注意。4.5 现象长时间运行后连接断开报 ISO : An error occurred during recv原因网络抖动、PLC 侧通信资源耗尽、或者电脑休眠导致 TCP 连接被回收。S7-300 的通信连接数有限多个客户端同时连容易挤掉。解决加心跳和重连机制捕获异常后client.disconnect()再client.connect()。采集程序里加个try/except包住读写操作断线后等几秒重连。下面这段是我常用的重连模板def safe_read(client, db, start, size, retry3): for i in range(retry): try: if not client.get_connected(): client.connect(192.168.0.10, 0, 2, 102) return client.db_read(db, start, size) except Exception as e: print(f读取失败第 {i1} 次重试: {e}) time.sleep(2) return None逻辑说明每次读之前先检查连接状态断了就重连最多重试retry次。参数retry按现场网络质量调一般 3 次够用网络差的可以加到 5 次。5. 进阶技巧批量采集、地址表驱动与一个验证习惯5.1 用地址表驱动采集别把偏移写死在代码里项目一多DB 块地址经常变把偏移量硬编码在 Python 里改一次就要动代码。我现在的做法是维护一张 Excel 或 CSV 地址表程序启动时读进来按表采集。变量名区域DB号偏移类型说明温度DB10Real反应釜温度计数DB14Int当日产量运行DB16.0Bool设备运行状态报警M010Bool综合报警位import pandas as pd from snap7.util import get_real, get_int, get_bool # 读取地址表 tags pd.read_excel(tags.xlsx) def read_tag(client, row): if row[区域] DB: data client.db_read(int(row[DB号]), int(row[偏移]), 4) else: data client.read_area(snap7.types.Areas.MK, 0, int(row[偏移]), 4) if row[类型] Real: return get_real(data, 0) elif row[类型] Int: return get_int(data, 0) elif row[类型] Bool: return get_bool(data, 0, 0) for _, row in tags.iterrows(): print(row[变量名], read_tag(client, row))逻辑说明地址表把变量名-区域-DB号-偏移-类型解耦出来程序只负责按表解析。参数上偏移列对 Bool 类型要写成6.0这种带位号的格式解析时拆开用。5.2 一个验证习惯先读已知值再上生产每次新项目接线完成我不会直接跑采集程序而是先手动在 PLC 里给几个测试变量赋已知值——比如温度写 25.0、计数写 100、运行位置 1——然后用 Python 读一遍确认读出来的和写进去的完全一致。这一步能同时验证 rack/slot、偏移量、数据类型三件事比逐个排查快得多。# 验证脚本读三个已知值和预期对比 data client.db_read(1, 0, 12) assert abs(get_real(data, 0) - 25.0) 0.01, 温度读取异常 assert get_int(data, 4) 100, 计数读取异常 assert get_bool(data, 6, 0) True, 运行状态读取异常 print(验证通过可以上生产采集)逻辑说明用assert做硬校验任何一项不匹配直接抛异常避免带着错误配置上生产。Real 值比较用容差因为浮点传输可能有微小误差。从那以后我每次新接一个 S7-300/400 的采集项目都强制先跑一遍这个已知值验证再开正式采集。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

【AI大模型】生产环境吞吐优化方案

【AI大模型】生产环境吞吐优化方案

【AI大模型】生产环境吞吐优化方案 生产环境部署大模型时,吞吐往往比单请求延迟更影响成本和体验。吞吐上不去,要么算力闲置、要么队列堆积。本文围绕一个核心问题展开:在显存和算力给定的条件下,如何最大化单位时间完成的请求数与生成 token 数。先讲清瓶颈在哪,再按调度…

2026/10/15 12:21:56 阅读更多 →
MCP与A2A:构建可工程化落地的多Agent系统

MCP与A2A:构建可工程化落地的多Agent系统

1. 这不是概念炒作,是工程落地的分水岭“多 Agent、MCP、A2A——最该补的一堂课”,这标题乍看像培训广告,实则戳中了当前智能系统开发里最真实、最普遍、也最容易被忽视的断层。我带过七支不同行业的AI工程团队,从金融风控后台到工…

2026/10/15 12:20:55 阅读更多 →
CPD级联部分解码器:显著目标检测的速度与精度平衡实践

CPD级联部分解码器:显著目标检测的速度与精度平衡实践

1. 为什么CPD值得单独拿出来聊显著目标检测这个方向,做过的人都知道,模型精度和推理速度几乎是一对天敌。早期的方法要么精度勉强能看但跑一张图要几百毫秒甚至上秒级,要么速度快但边缘糊成一团、小目标直接漏检。CVPR 2019那篇Cascaded Part…

2026/10/15 12:20:55 阅读更多 →

最新新闻

Qt跨数据库获取SQL表字段元数据的工程实践

Qt跨数据库获取SQL表字段元数据的工程实践

1. 项目概述:为什么“获取SQL数据表所有字段”是Qt开发中绕不开的硬需求在用Qt做数据库应用开发时,我几乎每天都会遇到这个场景:界面刚打开,需要动态加载某张表的全部字段名来构建查询条件面板;或者用户点开一个数据编…

2026/10/15 13:01:26 阅读更多 →
页面没有报截断,短屏上确认按钮却消失了:HarmonyOS 7 怎么验关键任务始终可达

页面没有报截断,短屏上确认按钮却消失了:HarmonyOS 7 怎么验关键任务始终可达

页面没有报截断,短屏上确认按钮却消失了:HarmonyOS 7 怎么验关键任务始终可达 DevEco Studio 26.0 场景化体检把“截断”纳入多设备检测,官方多设备指南也明确提醒短屏高度受限时要保证关键区可见并支持滚动。但最难发现的不是文字少一行&am…

2026/10/15 13:01:26 阅读更多 →
AI 卖课博主年入 120 万?程序员用 Cursor 算完这笔账,我沉默了

AI 卖课博主年入 120 万?程序员用 Cursor 算完这笔账,我沉默了

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 13:01:26 阅读更多 →
RetroArch BIOS 资源包:一键补齐多平台模拟器 BIOS 文件

RetroArch BIOS 资源包:一键补齐多平台模拟器 BIOS 文件

简介:这份资源面向复古游戏模拟器玩家与 Retropie、Recalbox、Lakka、Retrobat、EmuVR 等前端使用者,集中提供 libretro 体系所需的系统固件与 BIOS 文件,解决模拟器因缺少底层固件而无法启动或运行异常的问题。压缩包共 262 个文件&#xff…

2026/10/15 13:01:26 阅读更多 →
深入理解context-mode:给AI划边界,让编程更稳定、更省token

深入理解context-mode:给AI划边界,让编程更稳定、更省token

其实最开始我对context-mode这词挺不以为然,觉得不就是“多给AI塞点资料”吗?直到在项目里被坑了好几次,才意识到这观念错得离谱。有一阵子我习惯把项目里相关的文件全部丢给AI代码助手,结果它给的修改建议经常自相矛盾&#xff0…

2026/10/15 13:01:26 阅读更多 →
人脸特征提取三路线:HoG、Dlib与CNN原理及选型指南

人脸特征提取三路线:HoG、Dlib与CNN原理及选型指南

人脸识别这几年从实验室走向了门禁、考勤、相册聚类、甚至手机解锁,几乎成了计算机视觉里最"接地气"的方向之一。但真到动手做项目的时候,很多人会卡在同一个地方:特征到底怎么提?我见过不少朋友一上来就堆深度学习模型…

2026/10/15 13:00:25 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →