You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python Watchdog时内存未释放问题及内存重置方案咨询

内存占用问题与解决方案

问题背景

我用watchdog监控文件夹的文件创建操作,只要有parquet文件创建,watchdog就会调用Python脚本读取该文件。watchdog首次运行时内存占用90KB;读完第一个parquet文件后,内存涨到100KB——我已经在脚本执行完后删除了所有DataFrame。当第二个parquet文件创建时,watchdog启动脚本的初始内存是100KB,读完后变成101KB。

疑问

  1. 为什么第一个文件处理完后watchdog没释放内存?
  2. 怎么写脚本才能让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 04:25:20