任何没有引用的 CPython 对象都会立即被释放。Python 会定期进行垃圾回收来处理仅相互引用但程序无法访问的对象组(循环引用)。如果需要在特定时间(gc.collect()
)完成,您可以手动调用垃圾收集器来清除它们。这使得内存可供您的 Python 脚本重用,但可能会或可能不会立即(或永远)将该内存释放回操作系统。
CPython 在 256KB 的区域中分配内存,将其划分为 4KB 的池,这些池进一步细分为块,这些块被指定用于特定大小的对象(这些通常是类似类型,但不必如此)。该内存可以在 Python 进程中重复使用,但在整个竞技场为空之前它不会被释放回操作系统。
现在,在 2005 年之前,一些常用的对象类型并没有使用这种方案。例如,一旦您创建了一个“int”或“float”,即使它被 Python 释放,该内存也永远不会返回给操作系统,但它可以被重用于这些类型的其他对象。(当然 small int
s 是共享的,不会占用任何额外的内存,但是如果你分配了一个 large int
s 或float
s 的列表,即使在这些对象被释放后,CPython 也会保留该内存。)Python还保留了一些由列表和字典分配的内存(例如最近的 80 个列表)。
这都是根据本文档关于对 Python 内存分配器大约 2.3 版所做的改进。我知道从那时起已经做了一些进一步的工作,所以一些细节可能已经改变(int
/float
情况已根据下面 arbautjc 的评论纠正)但基本情况仍然存在:出于性能原因,Python 不会将所有内存返回到立即操作系统,因为malloc()
小分配的开销相对较高,并且碎片内存越多越慢。因此,Python 只有mallocs()
大块的内存并在这些块本身内分配内存,并且只有在它们完全为空时才将这些块返回给操作系统。
您可以尝试其他 Python 实现,例如 PyPy(旨在与 CPython 尽可能兼容)、Jython(在 JVM 上运行)或 IronPython(在 .NET CLR 上运行),看看它们的内存管理是否更符合你正在做的。如果您当前使用的是 32 位 Python,则可以尝试 64 位(假设您的 CPU 和操作系统支持它)。
但是,您从 shell 脚本顺序调用脚本的方法对我来说似乎非常好。您可以使用该subprocess
模块在 Python 中编写主脚本,但在 shell 中可能更简单。
但是,如果不了解您的脚本正在做什么,就很难猜测是什么导致了这种情况。