Python如何不阻塞主循环持续写入文件并实现优雅退出
解决方案
你原始代码的核心问题是直接调用WriteToFile()会阻塞主进程,导致后续的测量循环完全无法执行,我们通过多线程+停止标志位的方案就能满足你的需求,该方案兼容你当前使用的Python 3.5.3版本,无需升级。
核心修改思路
- 引入
threading模块将WriteToFile放到独立子线程运行,不阻塞主测量流程 - 新增全局停止标志位控制
WriteToFile的循环,避免暴力杀死线程导致文件未正常关闭 - 拆分10秒等待为小时间片轮询,保证停止命令可以快速响应
- 文件写入改用
with上下文管理器,自动处理文件关闭,避免资源泄漏
修改后完整代码
from datetime import datetime import os import time import sys import random import threading M_Max = 2000 M_Array = [740] D_Array = [5, 10, 20, 100, 150, 200, 400,600, 740] M=random.random()*20000 D=random.random()*7500 # 停止WriteToFile的标志位 stop_write_flag = False # 存储写文件子线程的对象 write_thread = None # write data to a file every ten seconds def WriteToFile(): global stop_write_flag while not stop_write_flag: # 使用with上下文管理器,自动关闭文件,即使写入出错也不会漏关 with open("FastFile.txt", "a") as h: current_time_t=datetime.now().strftime("%d.%m.%y %H:%M:%S") p = random.random()*1000 c = random.random()*100 print("Fast_Time :", '{} {:9.0f} {:9.0f} {:9.3f} {:9.1f} '.format(current_time_t, M, D, p, c)) h.write("\n %s , %s , %s , %s, %s " % ( current_time_t, str('{:.1f}'.format(M)), str('{:.1f}'.format(D)), str('{:.3f}'.format(p)), str('{:.2f}'.format(c)) )) # 拆分10秒等待为20次0.5秒等待,每次检查停止标志,响应更快 wait_cnt = 0 while wait_cnt < 20 and not stop_write_flag: time.sleep(0.5) wait_cnt += 1 print("WriteToFile已正常退出,FastFile.txt已关闭") def CleanUp(): global stop_write_flag, write_thread print("Cleaning up,等待2分钟后停止写文件") # 先等2分钟 time.sleep(120) # 设置停止标志 stop_write_flag = True # 等待子线程完全退出,确保文件操作完成 write_thread.join() print("Done") sys.exit() def main(): global M, D, write_thread # 启动写文件子线程 write_thread = threading.Thread(target=WriteToFile, daemon=True) write_thread.start() print("Starting measurement") time.sleep(3) for M in M_Array: for D in D_Array: p = random.random()*1000 c = random.random()*100 # 同样用with上下文管理器处理SlowFile的写入 with open("SlowFile.txt", "a") as g: current_time_t = datetime.now().strftime("%d.%m.%y %H:%M:%S") print("Main_Time :", '{} {:9.0f} {:9.0f} {:9.3f} {:9.1f} '.format(current_time_t, M, D, p, c)) g.write("\n %s , %s , %s , %s, %s " % ( current_time_t, str('{:.1f}'.format(M)), str('{:.1f}'.format(D)), str('{:.3f}'.format(p)), str('{:.2f}'.format(c)) )) CleanUp() if __name__ == "__main__": main()
关键说明
- 标志位控制退出可以保证
WriteToFile完成当前正在执行的写入操作后再退出,不会出现半行数据残留或者文件未关闭的问题 - 子线程读取全局变量
M、D属于简单原子操作,无需额外加锁就可以保证数据一致性,符合你的使用场景 - 如果你需要提前终止程序,只要触发
stop_write_flag = True再调用write_thread.join()就可以实现优雅退出
内容的提问来源于stack exchange,提问作者Buzz
相关产品推荐
相关产品推荐

