@profile装饰器需配合python -m memory_profiler运行才生效,否则无效;异步函数须改用memory_usage手动采样,其interval和timeout需依任务类型合理设置。

为什么 @profile 装饰器没输出?
直接加 @profile 却看不到内存报告,大概率是因为没用 memory_profiler 的专用执行方式。这个装饰器本身不生效,必须配合 python -m memory_profiler 运行脚本,否则只是个空壳。
- 错误做法:
python my_script.py——@profile完全被忽略 - 正确做法:
python -m memory_profiler my_script.py - 如果函数在模块中被间接调用(比如被
if __name__ == "__main__"外的代码触发),要确保该函数确实被执行到了,否则也不会打印分析行 - 注意:
@profile只对同步函数有效;异步函数需改用memory_usage手动采样
memory_usage 的 interval 和 timeout 怎么设才合理?
手动监控一段运行中的代码块时,memory_usage 的采样频率直接影响结果可信度和开销。太密会拖慢执行、干扰行为;太疏可能漏掉峰值。
-
interval=0.1(100ms)适合多数 CPU-bound 任务,能捕捉典型增长趋势 - IO 或网络等待多的场景,可放宽到
interval=0.5,避免大量无效采样 -
timeout必须略大于预期执行时间,否则提前终止返回空列表 —— 常见错误是设成timeout=1却跑了个 1.2s 的函数 - 示例:
mem_usage = memory_usage((my_func, (arg1,)), interval=0.1, timeout=5)
看到 Line # 后内存持续上涨,但代码里没明显对象累积?
这往往不是“忘了 del”,而是隐式引用没断开。常见于闭包、全局缓存、日志 handler、循环引用(尤其含 __del__ 或弱引用管理逻辑的对象)。
- 检查是否无意把局部变量塞进了模块级字典或类属性(比如
cache[key] = result但没清理机制) - 用
gc.get_referrers(obj)查谁还持有着疑似泄漏对象(需先用psutil.Process().memory_info().rss确认内存确实在涨) - 第三方库(如某些 pandas 操作、requests session、SQLAlchemy session)自带内部缓存,需显式关闭或复用
-
memory_profiler只显示每行分配量,不显示对象生命周期 —— 它告诉你“哪行吃得多”,但不解释“为什么还不释放”
为什么多进程下 memory_profiler 报告不准?
因为 memory_profiler 默认只监控主进程,子进程内存完全不计入。如果你用 multiprocessing 或 concurrent.futures,主进程内存可能稳定,但子进程各自暴涨后退出,总 RSS 仍飙升。
立即学习“Python免费学习笔记(深入)”;
- 解决办法一:在子进程中单独调用
memory_usage并打日志(需注意进程间不能共享@profile装饰器) - 解决办法二:用系统工具辅助验证,例如运行时执行
ps aux --sort=-%mem | head -10,看实际进程内存分布 - 注意:fork 模式下子进程初始内存与父进程共享,
memory_profiler的增量统计容易失真;spawn 模式更干净但启动开销大
weakref.finalize 验证回收时机。


















