尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从Python温湿度数据采集到数据库存储:完整实践指南

从Python温湿度数据采集到数据库存储:完整实践指南 简介一套围绕Python的温湿度数据采集、处理与数据库存储的综合项目源码主要面向物联网初学者、Python数据分析人员及需要搭建环境监测数据链路的开发者。项目完整实现了从传感器或网络接口获取原始数据经解析与清洗后写入MySQL数据库的流程涉及硬件接口通信、数据解析、数据库操作等关键知识点。压缩包共14个文件包含Python源文件、编译缓存文件与历史数据文件三类整体大小约11KB其中源文件为项目代码主体编译缓存可用于加速运行历史数据文件便于查看采集结果结构简洁且便于快速定位核心逻辑。目前已有825人学习下载。借助这套项目读者可掌握硬件通信、数据解析、缺失值处理、数据库表设计与写入等实操技巧也能将其作为课程设计、毕业设计或物联网数据采集项目的参考起点。 上个月朋友找我帮忙搭一套库房温湿度监测系统说实话一开始我也没当回事觉得不就是读个传感器、记个数据嘛。等真上手才发现从Python温湿度数据测量到数据处理再到数据库存储这条链路里值得琢磨的细节非常多。后台也一直有人问类似的需求干脆把这次实践完整拆开聊聊从硬件取数到数据落库的全过程给做环境监测、仓库管理、设备巡检这类项目的朋友一个参考。这套流程能解决什么问题把传感器读回来的原始值变成干净、连续、可回溯的历史数据。适合刚接触Python和数据采集的开发者也适合想把硬件数据管起来的嵌入式爱好者。我尽量把每个环节的选型理由和踩坑点都讲清楚你可以直接照着搭。1. 整体思路与方案选型1.1 一个项目拆成三个阶段先说清楚整体链路。典型的温湿度数据系统可以拆成三块数据测量、数据处理、数据存储。测量传感器定时采集环境的温度和相对湿度生成一条带时间戳的记录。处理对原始读数做去抖、滤波、异常值剔除、时间对齐让它变成能直接用、能长期存的数据。存储把处理后的数据写入数据库方便后续查询、统计、做可视化。这三块不是独立存在的。数据格式怎么定直接影响解析代码写起来是否顺手存储字段怎么设计决定了后面能不能按设备、按时间段方便地查数据。所以动手前先把数据流在脑子里过一遍比直接写代码重要得多。1.2 为什么用 Python 做这套东西在众多可选方案里我最终选择Python主要是两个原因一是生态完整串口通信有pyserial科学计算有numpy和pandas数据库有内置的sqlite3基本不需要额外造轮子二是调试效率高从读串口到入库代码量很克制出了问题也能很快定位。对个人或小团队来说这是把硬件采集和数据管理结合得最舒服的组合。数据库选型我用的是SQLite而不是MySQL。原因很直接单文件、零配置、跨平台Python标准库自带支持开箱即用。如果是个人项目、小规模部署SQLite完全够用。只有到了多设备并发写入、需要远程访问数据库时再考虑MySQL这类服务型数据库也不迟。我从实际需求出发做了个对比对比项SQLiteMySQL部署复杂度零配置单个文件需要安装服务、创建账号并发能力适合低并发读写适合高并发、多人访问数据迁移直接拷贝文件需要导出导入适用场景单机采集、个人项目多客户端、服务端应用1.3 传感器和设备怎么选硬件这部分不同需求差别很大。我给个常见的选型参考传感器型号精度适合场景注意事项DHT11温度±2℃湿度±5%低成本入门响应慢容易抖动DHT22/AM2302温度±0.5℃湿度±2%一般环境监测价格适中精度够用AHT20温度±0.3℃湿度±2%小体积集成I2C接口驱动简单BME280温度±1℃湿度±3%需要气压补偿的场合功能多功耗低实际项目里很多人会用ESP32或STM32之类的开发板接传感器再通过串口把数据发给电脑上的Python程序处理。这种设备端采集、PC端处理存储的组合在实验室、库房、机房等场景都很常见。选型时根据精度需求和预算来定不需要一味追求高精度传感器。2. 温湿度数据采集先把原始数据拿回来2.1 串口协议的约定不管用ESP32还是STM32设备端输出的数据最终大多会通过串口传出来。常见做法是设备按固定格式发送字符串比如T25.3,H60.1每条记录用换行符结尾。这样PC端只需要按行读取再简单解析即可。这里有一个建立项目的关键点在写设备端代码之前先把输出格式定好包括字段顺序、分隔符、小数位数、换行符不然后面两边联调会很痛苦。2.2 PC端通过串口读取数据的代码PC端用Python接收这些数据核心就是pyserial。先安装依赖pip install pyserial然后写一个最小的读取循环import serial ser serial.Serial( portCOM3, # Windows 下是 COMxLinux 下是 /dev/ttyUSB0 baudrate115200, timeout2 ) try: while True: line ser.readline() if not line: continue text line.decode(utf-8).strip() if text: print(text) except KeyboardInterrupt: pass finally: ser.close()这段代码里有两个容易踩坑的地方。第一是串口号Windows下要在设备管理器里查看实际COM号Linux下要确认设备有读写权限。第二是编码方式有的设备输出GBK有的输出UTF-8解码出错时先看看设备文档。2.3 设备不在手边怎么继续开发我开发时遇到一个实际问题传感器在朋友那边代码在自己这边没法实时调试。这种情况我建议先用模拟数据把流程跑通。简单生成模拟温湿度数据的代码import random import time def read_simulated_data(): temperature round(random.uniform(20.0, 30.0), 2) humidity round(random.uniform(40.0, 70.0), 2) return temperature, humidity while True: t, h read_simulated_data() print(f模拟数据 T{t}, H{h}) time.sleep(2)在数据处理和数据库阶段先用模拟数据验证逻辑最后再接真实设备能省掉大量排错时间。3. 数据处理把毛糙的读数洗干净3.1 原始数据为什么不能直接用传感器数据不是拿回来就能入库的主要原因有三个一是传感器读数有波动。尤其是DHT11这类低端传感器温度波动一两度、湿度波动百分之几都很常见。直接存原始值后面做趋势分析时会看到大量毛刺。二是难免有异常值。传感器偶发吐出一个离谱的数值比如温度读到-40度可能是接线问题也可能是干扰。不处理的话平均值都会被带偏。三是时间戳不整齐。设备可能不定时发数据收到后要统一加时间戳否则入库后很难按时间段排序分析。3.2 用阈值和滤波把异常值挡在外面我通常先做两步物理范围判断再加滑动滤波。物理范围判断很简单温度和湿度都有一个合理区间超出区间直接丢弃。代码def is_valid(temp, humi): # 合理的温度和湿度范围 return -20.0 temp 60.0 and 0.0 humi 100.0这一步能把离谱的野值清掉。然后是滑动平均滤波对连续采集的数据很有效from collections import deque class MovingAverageFilter: def __init__(self, window_size10): self.window deque(maxlenwindow_size) def add(self, value): self.window.append(value) return sum(self.window) / len(self.window)实测下来5秒采一次数据窗口设10也就是50秒的平均就能把DHT11的抖动压得很平滑。窗口大小怎么定温度变化慢的场景可以大一点想要快速感知温度突变就调小。这个值需要根据你的采样频率和实际需求来调没有标准答案。如果还想更稳一点可以用中值滤波代替均值滤波对个别尖峰有更强的抵抗能力。均值滤波适合平滑随机噪声中值滤波适合剔除偶发毛刺实战中我会先做中值再做均值。3.3 时间戳和汇总统计处理完实时数据后还有一个环节容易被忽略数据汇总。原始数据可能是每5秒一条存一个月就是50多万条。长期分析时我们往往只需要每分钟均值、每小时均值。所以我会在数据入库的同时定期生成汇总表def calc_hourly_mean(records): # records 是一小时内所有记录 temp_mean sum(r[temp] for r in records) / len(records) humi_mean sum(r[humi] for r in records) / len(records) return round(temp_mean, 2), round(humi_mean, 2)汇总表既能减轻长期存储压力查询报表时速度也快得多。这个思路在工业数据采集里叫降采样原理就是牺牲一点时间分辨率换存储和查询效率。4. 数据库存储让数据真正落地4.1 表结构怎么设计到了存储环节用SQLite最省心。一张表就够了CREATE TABLE IF NOT EXISTS sensor_data ( id INTEGER PRIMARY KEY AUTOINCREMENT, device_id TEXT NOT NULL, temperature REAL NOT NULL, humidity REAL NOT NULL, measured_at TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_device_time ON sensor_data (device_id, measured_at);字段设计有几个值得注意的点。device_id 必须要有哪怕当前只有一个传感器。有了它以后加设备不用改表结构。measured_at 用ISO格式字符串比如2025-01-15 10:30:00这种格式可以像字符串一样排序也能直接被大多数图表工具识别。给device_id和measured_at建联合索引是因为后续查询基本都按设备和时间过滤没有索引会越来越慢。4.2 插入数据别用一条一条的方式最简单的插入方式是一条一条执行但实测很慢。我推荐用executemany批量插入import sqlite3 def save_records(records): conn sqlite3.connect(env_data.db) cursor conn.cursor() rows [ (r[device_id], r[temperature], r[humidity], r[measured_at]) for r in records ] cursor.executemany( INSERT INTO sensor_data (device_id, temperature, humidity, measured_at) VALUES (?, ?, ?, ?), rows ) conn.commit() conn.close()同样是1000条数据单条插入可能要几百毫秒executemany打包插入通常几十毫秒就能完成。量小可能无所谓数据量大、采集频繁时差距非常明显。记住一点批量插入时一定要用同一个连接操作完哪怕忘了提交也要用try/finally确保连接关闭。4.3 SQLite并发写入的问题SQLite不是服务器型数据库默认情况下多个进程同时写会报database is locked。我之前犯过这个错一边让采集脚本写库一边开了数据可视化工具查库结果写入进程时不时中断。解决办法有两个。一是让采集程序保持持续连接不要每写一条就重新打开关闭。二是开启WAL模式并设置busy_timeoutPRAGMA journal_modeWAL; PRAGMA busy_timeout5000;WAL模式允许读写并行busy_timeout让写入进程在锁释放前等待实测稳定性提升非常明显。长期跑下来SQLite文件会越来越大。我通常会做两件事超过半年的原始明细定期清理只保留汇总数据或者用单独脚本把一个月前的明细迁移到历史表主表保持轻量。5. 常见问题与排查技巧实录5.1 问题速查表把我在这个项目里遇到的典型问题整理成了表格方便对号入座现象可能原因解决办法串口打开失败串口号不对、被其他程序占用、权限不足检查COM/TTY设备号关闭占用程序Linux下加用户到dialout组读取内容乱码波特率不匹配、编码方式错误核对设备端波特率尝试UTF-8/GBK解码数据断断续续串口超时太短、设备供电不稳调大timeout检查传感器供电是否稳定插入报database is locked多进程同时写、未用WAL开启WAL模式设置busy_timeout传感器读数长时间不变设备死机、串口缓冲区堆积重启设备检查解析逻辑是否有阻塞点打包exe后读不到数据串口库或依赖未正确打包用pyinstaller的--hidden-import选项补充pyserial等模块5.2 几个值得注意的细节串口超时参数我习惯设成2秒。太短设备响应慢时容易读空太长程序退出时不灵敏。设备恢复后要让脚本能自动重连可以加一个异常重连机制while True: try: ser serial.Serial(COM3, 115200, timeout2) break except serial.SerialException: print(串口未就绪5秒后重试...) time.sleep(5)另外把配置文件独立出来是个好习惯。串口号、波特率、数据库文件名、采样间隔这些参数统一放到config.py或者配置文件里避免改环境时到处翻代码。5.3 从Python到可交付的脚本如果这套程序最后要交给别人跑建议先别急着打包exe。把依赖写进requirements.txt提供简单的启动脚本部署起来比exe更灵活。真要打包用pyinstaller时注意包含隐藏导入模块并在Windows上确认串口号在目标机器上的变化。我个人建议做个简单的命令行参数比如指定串口号、指定采样间隔这样到现场调试时不用改代码直接传参数就能适配不同设备。最后说点实际的。这个项目从前到后做完我自己最大的收获是把测量-处理-存储这三件事串起来想比单独写某个环节的代码重要得多。一开始我只想着怎么把传感器数据读出来后来发现数据处理和存储设计才是决定系统好不好用的关键。再分享一个小技巧先用模拟数据把全链路跑通再接真实设备。我在第二次做类似项目时直接用这个流程连硬件都不用等程序框架先写好设备一到换一个数据读取函数就能上线。这套思路做环境监测也好、做设备巡检也罢都能帮你节省大量联调时间。如果你也在搞类似的数据采集项目不妨照着这个闭环试一遍。本文还有配套的精品资源点击获取
返回列表