使用Python Watchdog时内存未释放问题及内存重置方案咨询
内存占用问题与解决方案
问题背景
我用watchdog监控文件夹的文件创建操作,只要有parquet文件创建,watchdog就会调用Python脚本读取该文件。watchdog首次运行时内存占用90KB;读完第一个parquet文件后,内存涨到100KB——我已经在脚本执行完后删除了所有DataFrame。当第二个parquet文件创建时,watchdog启动脚本的初始内存是100KB,读完后变成101KB。
疑问
- 为什么第一个文件处理完后watchdog没释放内存?
- 怎么写脚本才能让watchdog每次处理完文件后重置内存?也就是处理第一个文件时初始90KB、结束100KB;处理第二个文件时初始回到90KB、结束100KB,而不是从100KB开始。
问题1:内存未释放的原因
- Python的垃圾回收(GC)虽会回收无用对象,但操作系统不会立即将回收的内存归还给系统。Python解释器会保留这部分内存作为内存池,供后续对象分配使用,避免频繁向系统申请/释放内存的性能损耗。
- pandas读取parquet时,除了DataFrame本身,还可能加载底层依赖库的缓存、临时对象,这些内存要么无法被完全清理,要么被Python内存池留存。
gc.collect()仅触发Python层面的垃圾回收,但回收后的内存仍属于当前进程,操作系统不会立刻收回,所以进程内存占用无法回到初始的90KB。
问题2:重置内存的解决方案
要实现每次处理文件的初始内存回到90KB,核心是让文件处理逻辑在独立子进程中运行。子进程结束后,操作系统会自动回收其所有内存,主进程(watchdog)的内存就能保持初始状态。
修改后的脚本示例
读取parquet的脚本(utility/python_script.py)
import os import pandas as pd import gc, psutil def usage(): process = psutil.Process(os.getpid()) return process.memory_info()[0]/float(2**20) def readfile(filename): gc.enable() print("Before reading parquet: "+str(usage())) df = pd.read_parquet(filename) print("After reading parquet: "+str(usage())) del df gc.collect() print("After deleting df: "+str(usage())) if __name__ == "__main__": import sys if len(sys.argv) > 1: readfile(sys.argv[1])
Watchdog监控脚本
import os, sys, time from watchdog.observers.polling import PollingObserver from watchdog.events import FileSystemEventHandler import subprocess class MonitorFolder(FileSystemEventHandler): def on_created(self, event): filename = event.src_path # 仅处理parquet文件 if filename.endswith('.parquet'): # 启动独立子进程执行读取逻辑 script_path = os.path.join(os.path.dirname(__file__), 'utility/python_script.py') subprocess.run([sys.executable, script_path, filename]) if __name__=="__main__": path_ = "C:\\folder1\\folder2" event_handler = MonitorFolder() observer = PollingObserver(timeout=0.1) observer.schedule(event_handler, path=path_, recursive=True) observer.start() try: while True: time.sleep(0.1) except KeyboardInterrupt: observer.stop() observer.join()
原理说明
- 每次检测到parquet文件创建,watchdog主进程会启动全新子进程执行读取任务。
- 子进程完成后自动退出,操作系统会彻底回收其占用的所有内存,主进程内存始终维持在初始的90KB左右。
- 这种方式完全隔离了每次文件处理的内存环境,从根源上解决了内存累积问题。
内容的提问来源于stack exchange,提问作者Susan
相关产品推荐
相关产品推荐

