树莓派Python流量计采数仅写单条CSV,如何让每次循环新增数据行
树莓派流量计CSV连续采集修复方案
问题根因
你遇到的CSV文件仅保留一行记录的核心原因是:每次循环都使用w(覆盖写入)模式打开CSV文件,每次写入操作都会清空文件原有内容,最终仅会保留最后一次循环的写入结果。同时每次循环重复写入表头也不符合CSV文件的格式规范。
核心修改点
- 将CSV文件初始化、表头写入逻辑移至
while循环外部,避免重复覆盖文件、重复写入表头 - 调整
time.sleep(5)的位置,避免采集的时间戳与实际写入时间存在5秒偏差 - 新增GPIO清理逻辑,避免脚本退出后引脚状态触发异常警告
修改后完整代码
import json import time from datetime import datetime, timedelta import RPi.GPIO as GPIO import csv class FlowMeter(): ''' Class representing the flow meter sensor which handles input pulses and calculates current flow rate (L/min) measurement ''' def __init__(self): self.flow_rate = 0.0 self.last_time = datetime.now() def pulseCallback(self, p): ''' Callback that is executed with each pulse received from the sensor ''' # Calculate the time difference since last pulse recieved current_time = datetime.now() diff = (current_time - self.last_time).total_seconds() # Calculate current flow rate hertz = 1. / diff self.flow_rate = hertz / 7.5 # Reset time of last pulse self.last_time = current_time def getFlowRate(self): ''' Return the current flow rate measurement. If a pulse has not been received in more than one second, assume that flow has stopped and set flow rate to 0.0 ''' if (datetime.now() - self.last_time).total_seconds() > 1: self.flow_rate = 0.0 return self.flow_rate def main(): ''' Main function for repeatedly collecting flow rate measurements and sending them to the SORACOM API ''' # Configure GPIO pins INPUT_PIN = 7 GPIO.setmode(GPIO.BOARD) GPIO.setup(INPUT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Init FlowMeter instance and pulse callback flow_meter = FlowMeter() GPIO.add_event_detect(INPUT_PIN, GPIO.RISING, callback=flow_meter.pulseCallback, bouncetime=20) end_time = datetime.now() + timedelta(minutes=5) # 提前打开CSV文件,写入表头 header = ['Time','Flow Rate'] with open('flowrate.csv', 'w', encoding='UTF8', newline='') as f: writer = csv.writer(f) writer.writerow(header) while True: timestamp = str(datetime.now()) flow_rate = flow_meter.getFlowRate() print('Timestamp: %s' % timestamp) print('Flow rate: %f' % flow_rate) # 写入当前采集数据 writer.writerow([timestamp, flow_rate]) if datetime.now() > end_time: break # 等待5秒进行下一次采集 time.sleep(5) # 脚本退出前清理GPIO状态 GPIO.cleanup() if __name__ == '__main__': main()
可选高可靠性写入方案
如果担心脚本中途异常断电、进程被杀导致已采集数据丢失,可以改用每次循环追加写入的模式,无需保持文件长期打开,修改步骤如下:
- 导入os模块判断文件是否存在:在代码开头新增
import os - 把循环内的写入逻辑替换为如下代码即可:
header = ['Time','Flow Rate'] data = [timestamp, flow_rate] # 判断文件是否存在,不存在则先写入表头 file_exists = os.path.exists('flowrate.csv') with open('flowrate.csv', 'a', encoding='UTF8', newline='') as f: writer = csv.writer(f) if not file_exists: writer.writerow(header) writer.writerow(data)
该方案每次写入后都会自动落盘保存,5秒一次的采集频率下性能损耗可以忽略。
内容的提问来源于stack exchange,提问作者Jackson A Swan
相关产品推荐
相关产品推荐

