Python 3.5基于watchgod实现文件监视器的阻塞问题求助
解决watchgod监控时被任务阻塞的问题
Hey Rajat, 我完全懂你的困扰——当你用os.system()调用另一个脚本时,主线程会被死死卡住,直到那个脚本跑完才会继续监控目录,这期间新增的文件自然就被漏掉了。咱们用多线程就能轻松解决这个并行执行的问题,让监控和任务处理互不干扰。
问题根源
os.system()是个阻塞式调用:它会暂停当前线程,一直等split_thread_module.py执行完才会回到watch的循环里。这就相当于监控在任务运行期间“罢工”了,肯定抓不到新文件。
解决方案:用多线程异步处理任务
我们把执行脚本的逻辑拆到单独的线程里,这样主线程能继续跑watch的监控循环,新线程独立处理文件任务,两者并行运行。Python自带的threading模块用法简单,非常适合你的场景。
修改后的完整代码
print("execution of main file begins !!!!") import os import threading from watchgod import watch # 单独定义处理文件的函数,方便线程调用 def process_new_file(file_path): # 给文件路径加双引号,避免路径含空格时命令解析出错 os.system(f'python split_thread_module.py "{file_path}"') # 监控目录的主循环 for changes in watch(r'C:\Users\Rajat.Malik\Desktop\Requests'): # 遍历每一条目录变化记录 for change_type, file_location in changes: # 只处理新增的文件(change_type == 1对应watchgod的新增事件) if change_type == 1: # 启动新线程处理文件,主线程立刻回到监控状态 worker_thread = threading.Thread(target=process_new_file, args=(file_location,)) worker_thread.start() # 不需要等待线程结束,主线程继续监控即可
额外优化建议
- 处理含空格的路径:我在代码里给
file_path套了双引号,这样如果你的文件/文件夹名称有空格,命令也能正确识别,不会报错。 - 控制并发线程数:如果短时间内有大量文件新增,可能会创建太多线程占用资源。你可以用
ThreadPoolExecutor限制并发数(Python3.5完全支持),示例如下:
from concurrent.futures import ThreadPoolExecutor # 初始化线程池,最多同时跑5个任务 executor = ThreadPoolExecutor(max_workers=5) for changes in watch(r'C:\Users\Rajat.Malik\Desktop\Requests'): for change_type, file_location in changes: if change_type == 1: executor.submit(process_new_file, file_location)
- 用subprocess替代os.system:
subprocess.Popen是更灵活的非阻塞调用方式,能捕获脚本的输出和错误信息,比如:
import subprocess def process_new_file(file_path): subprocess.Popen(['python', 'split_thread_module.py', file_path])
这样修改后,你的监视器就能一边处理文件任务,一边实时监控目录变化,再也不会漏掉新增文件啦!
内容的提问来源于stack exchange,提问作者Rajat
相关产品推荐
相关产品推荐

