如何在RPI3网络监控脚本中安全终止无预设退出条件的无限循环?
解决树莓派3网络监控脚本的XLSX保存问题
嘿,这个问题我之前在树莓派上做监控脚本时也碰到过!xlsxwriter的“只能新建写入、无法编辑现有文件”特性加上无限循环的退出问题,确实让人头疼,不过有几个靠谱的解决方案,我给你梳理一下:
方案1:用信号处理捕获终止信号,触发文件保存
这是最直接的解决办法——给脚本加上信号监听,当你按下Ctrl+C或者系统发送终止信号时,自动执行workbook.close()保存文件,而不是直接强制终止。
代码示例:
import signal import xlsxwriter import time # 初始化Excel工作簿和工作表(循环外只做一次) workbook = xlsxwriter.Workbook('network_speed.xlsx') worksheet = workbook.add_worksheet() current_row = 0 # 写入表头 worksheet.write(current_row, 0, '时间') worksheet.write(current_row, 1, '下载速度') worksheet.write(current_row, 2, '上传速度') current_row += 1 # 定义退出处理函数 def graceful_exit(signum, frame): print("\n收到终止信号,正在保存数据...") workbook.close() print("Excel文件已保存,程序正常退出") exit(0) # 注册信号监听:捕获Ctrl+C(SIGINT)和系统终止信号(SIGTERM) signal.signal(signal.SIGINT, graceful_exit) signal.signal(signal.SIGTERM, graceful_exit) # 无限循环的监控逻辑 while True: # -------------------------- # 这里替换成你的网络速度获取代码 now = time.strftime("%Y-%m-%d %H:%M:%S") download = "120Mbps" # 实际获取的下载速度 upload = "60Mbps" # 实际获取的上传速度 # -------------------------- # 写入当前数据到内存中的工作表 worksheet.write(current_row, 0, now) worksheet.write(current_row, 1, download) worksheet.write(current_row, 2, upload) current_row += 1 time.sleep(5) # 每隔5秒监控一次
优点:
- 逻辑简单,不需要改原有监控流程
- xlsxwriter的内存缓存机制能保证写入效率,只有在退出时一次性写入磁盘
注意:
如果程序因为意外崩溃(比如断电),内存中未保存的数据还是会丢失,适合对数据完整性要求不是极高的场景。
方案2:用CSV临时存储+OpenPyXL转存Excel
如果担心意外崩溃丢数据,可以先用CSV文件实时追加数据(CSV支持追加写入),再定期用OpenPyXL把CSV数据同步到Excel文件——OpenPyXL支持编辑现有Excel文件,完美弥补xlsxwriter的短板。
代码示例:
import csv import time from openpyxl import Workbook, load_workbook # 定义CSV转Excel的函数 def sync_csv_to_excel(csv_path, excel_path): # 读取CSV所有数据 with open(csv_path, 'r', newline='', encoding='utf-8') as f: csv_reader = csv.reader(f) all_data = list(csv_reader) # 写入/更新Excel文件 try: # 如果Excel已存在,加载后覆盖数据(保留表头) wb = load_workbook(excel_path) ws = wb.active # 清空原有数据(从第2行开始) for row in ws.iter_rows(min_row=2): for cell in row: cell.value = None # 写入新数据 for row_idx, row_data in enumerate(all_data, 1): for col_idx, value in enumerate(row_data, 1): ws.cell(row=row_idx, column=col_idx, value=value) except FileNotFoundError: # 如果Excel不存在,新建并写入所有数据 wb = Workbook() ws = wb.active for row_data in all_data: ws.append(row_data) wb.save(excel_path) wb.close() # 初始化CSV文件(写入表头) csv_file = 'network_speed_temp.csv' with open(csv_file, 'w', newline='', encoding='utf-8') as f: csv_writer = csv.writer(f) csv_writer.writerow(['时间', '下载速度', '上传速度']) loop_counter = 0 while True: # -------------------------- # 替换成你的网络速度获取逻辑 now = time.strftime("%Y-%m-%d %H:%M:%S") download = "120Mbps" upload = "60Mbps" # -------------------------- # 追加数据到CSV(实时写入磁盘,不会丢) with open(csv_file, 'a', newline='', encoding='utf-8') as f: csv_writer = csv.writer(f) csv_writer.writerow([now, download, upload]) # 每10次循环同步一次到Excel(可根据需求调整频率) loop_counter += 1 if loop_counter % 10 == 0: sync_csv_to_excel(csv_file, 'network_speed.xlsx') print(f"{now}:已同步数据到Excel") time.sleep(5)
优点:
- 即使程序崩溃,CSV里的所有数据都不会丢失
- Excel文件可以随时查看最新数据,不需要等程序退出
注意:
同步频率不要太高(比如不要每次循环都同步),避免频繁IO操作占用树莓派资源。
方案3:直接用OpenPyXL实时写入Excel
如果不想用CSV中转,也可以直接用OpenPyXL每次循环打开Excel文件追加数据,然后保存关闭——虽然每次循环都有IO操作,但树莓派3的性能完全能应付。
代码示例:
import time import signal from openpyxl import Workbook, load_workbook excel_file = 'network_speed.xlsx' # 初始化Excel文件和表头 try: wb = load_workbook(excel_file) ws = wb.active # 检查是否存在表头,没有就添加 if ws.cell(row=1, column=1).value != '时间': ws.append(['时间', '下载速度', '上传速度']) except FileNotFoundError: wb = Workbook() ws = wb.active ws.append(['时间', '下载速度', '上传速度']) wb.save(excel_file) wb.close() # 定义退出处理函数 def graceful_exit(signum, frame): print("\n程序正常退出") exit(0) signal.signal(signal.SIGINT, graceful_exit) signal.signal(signal.SIGTERM, graceful_exit) while True: # -------------------------- # 替换成你的网络速度获取逻辑 now = time.strftime("%Y-%m-%d %H:%M:%S") download = "120Mbps" upload = "60Mbps" # -------------------------- # 打开Excel追加数据 wb = load_workbook(excel_file) ws = wb.active ws.append([now, download, upload]) wb.save(excel_file) wb.close() # 显式关闭释放资源 time.sleep(5)
优点:
- 数据实时保存到Excel,随时可以查看
- 不需要额外维护CSV文件
注意:
每次循环的IO操作会比内存缓存慢一点,但对于5秒一次的监控来说完全可以忽略。
内容的提问来源于stack exchange,提问作者Bjamse
相关产品推荐
相关产品推荐

