概述

在 Python 中,内存管理涉及到一个包含所有 Python 对象和数据结构的私有堆(heap)。这个私有堆的管理由内部的 Python 内存管理器(Python memory manager) 保证。Python 内存管理器有不同的组件来处理各种动态存储管理方面的问题,如共享、分割、预分配或缓存。

在最底层,一个原始内存分配器通过与操作系统的内存管理器交互,确保私有堆中有足够的空间来存储所有与 Python 相关的数据。在原始内存分配器的基础上,几个对象特定的分配器在同一堆上运行,并根据每种对象类型的特点实现不同的内存管理策略。例如,整数对象在堆内的管理方式不同于字符串、元组或字典,因为整数需要不同的存储需求和速度与空间的权衡。因此,Python 内存管理器将一些工作分配给对象特定分配器,但确保后者在私有堆的范围内运行。

Python 堆内存的管理是由解释器来执行,用户对它没有控制权,即使他们经常操作指向堆内内存块的对象指针,理解这一点十分重要。Python 对象和其他内部缓冲区的堆空间分配是由 Python 内存管理器按需通过本文档中列出的 Python/C API 函数进行的。

为了避免内存破坏,扩展的作者永远不应该试图用 C 库函数导出的函数来对 Python 对象进行操作,这些函数包括: malloc(), calloc(), realloc()free()。这将导致 C 分配器和 Python 内存管理器之间的混用,引发严重后果,这是由于它们实现了不同的算法,并在不同的堆上操作。但是,我们可以安全地使用 C 库分配器为单独的目的分配和释放内存块,如下例所示:

  1. PyObject *res;
  2. char *buf = (char *) malloc(BUFSIZ); /* for I/O */
  3. if (buf == NULL)
  4. return PyErr_NoMemory();
  5. ...Do some I/O operation involving buf...
  6. res = PyBytes_FromString(buf);
  7. free(buf); /* malloc'ed */
  8. return res;

在这个例子中,I/O 缓冲区的内存请求是由 C 库分配器处理的。Python 内存管理器只参与了分配作为结果返回的字节对象。

然而,在大多数情况下,建议专门从 Python 堆中分配内存,因为后者由 Python 内存管理器控制。例如,当解释器扩展了用 C 写的新对象类型时,就必须这样做。使用 Python 堆的另一个原因是希望*通知* Python 内存管理器关于扩展模块的内存需求。即使所请求的内存全部只用于内部的、高度特定的目的,将所有的内存请求交给 Python 内存管理器能让解释器对其内存占用的整体情况有更准确的了解。因此,在某些情况下,Python 内存管理器可能会触发或不触发适当的操作,如垃圾回收、内存压缩或其他预防性操作。请注意,通过使用前面例子中所示的 C 库分配器,为 I/O 缓冲区分配的内存会完全不受 Python 内存管理器管理。

参见

环境变量 PYTHONMALLOC 可被用来配置 Python 所使用的内存分配器。

环境变量 PYTHONMALLOCSTATS 可以用来在每次创建和关闭新的 pymalloc 对象区域时打印 pymalloc 内存分配器 的统计数据。