Python查看变量及对象占用内存情况
在Python编程中,我们经常需要处理大量数据,这可能会导致内存使用量增加。了解哪些变量占用了大量内存对于优化程序性能和避免内存泄漏至关重要。本文将介绍如何在Python中查看变量及对象占用的内存大小。
在之前的文章中,我们也介绍过 基于psutil库监控程序的内存占用量 的方法,参见博客:Python 监控程序的内存占用量
其中,psutil 库可以用来获取与操作系统相关的统计信息,如CPU使用率、内存使用率、磁盘使用情况等。其提供的是整个系统的内存使用概况,而不是单个进程或对象的内存使用情况。
在本篇博客中,我们重点关注单个变量或对象占用内存的情况。
1. sys.getsizeof()函数
sys.getsizeof() 是Python标准库中的一个函数,它返回的是一个对象直接占用的内存量。
这个函数对于基本数据类型(如int, str, bytes等)来说,可以给出一个准确的内存占用大小(字节数)。
使用说明:
代码示例:
import sys
a = [1, 2, 3, 4, 5]
memory_size = sys.getsizeof(a) # 获取列表对象本身的大小
print(f"Memory size of my_list: {memory_size} bytes")
输出如下:
Memory size of a: 112 bytes
这里,sys.getsizeof()
函数只能返回对象a本身的内存使用情况,而不包括它引用的其他对象的内存使用情况。
2. pympler.asizeof()函数
pympler.asizeof() 函数是来自第三方库Pympler的一个函数,它不仅计算对象本身的内存消耗,还会递归地计算该对象引用的所有其他对象的内存消耗总和。 这意味着它考虑到了对象内部的数据结构以及这些内部对象的内存使用情况。
因此,如果你想要得到一个更接近实际情况的内存使用估计,尤其是对于包含复杂内部结构的对象(例如,包含多个嵌套列表或字典的对象),那么使用 pympler.asizeof() 通常是一个更好的选择。
首先,需要安装pympler库:
pip install pympler
然后,使用asizeof()
函数查看变量的内存使用情况。代码示例:
from pympler import asizeof
a = [1, 2, 3, 4, 5]
memory_size = asizeof.asizeof(a)
print(f"Total memory size of a: {memory_size} bytes")
输出如下:
Total memory size of a: 272 bytes
这里,asizeof(a)
函数输出了对象a及其引用对象所占用的总内存大小。
【注意】:pympler.asizeof()函数的实现相对复杂,因为需要递归地遍历对象图,以确保所有相关的子对象都被计入总大小。因此,asizeof.asizeof() 在某些情况下可能会消耗较多的内存和 CPU 资源。 具体取决于:
3. 第三方库 memory_profiler
memory_profiler
是一个第三方库,它可以用来监视内存消耗,特别是对于函数和方法的内存使用情况。它提供了一个装饰器 @profile
,可以用来分析函数的内存使用情况。
首先安装memory-profiler库:
pip install memory-profiler
然后使用 @profile
装饰器来监视函数内的内存使用情况。代码示例:
from memory_profiler import profile
@profile
def test():
a = [i for i in range(10000)]
test()
这将输出每个带有 @profile 装饰器的函数的内存使用情况报告,报告中会显示每次调用时内存使用的变化情况,具体如下:
Line # Mem usage Increment Occurrences Line Contents
=============================================================
17 81.0 MiB 81.0 MiB 1 @profile
18 def test():
19 81.4 MiB 0.4 MiB 10003 a = [i for i in range(10000)]
另外,memory_profiler 提供了一个 mem_usage 函数,可以用来获取当前时刻的内存使用情况:
4. 对比分析
sys.getsizeof(): 该函数是 Python 标准库的一部分,用于获取对象本身的内存大小。具有如下特点:
pympler.asizeof() :pympler 库中的一个函数,它可以递归地计算对象及其所有引用对象的内存大小。具有如下特点:
@profile 装饰器:是 memory_profiler 库提供的功能,主要用于分析函数级别的内存使用情况。它通过跟踪函数执行期间的内存变化来提供详细的报告。具有如下特点:
【总结分析】:
- 如果你只需要知道单个对象的基本内存大小,并且不需要考虑对象内部引用的内存消耗,那么 sys.getsizeof() 就足够了。
- 如果关心的是一个复合对象及其内部结构的整体内存大小,那么 pympler.asizeof() 是最合适的选择。
- 如果需要了解整个函数执行期间的内存使用情况,包括最大内存使用量和详细的内存变化,那么 @profile 装饰器是合适的选择。
根据具体需求,可以选择最适合的方法来评估内存使用情况。在开发阶段,为了找到潜在的内存泄漏或者优化内存使用,这些工具都是非常有用的。
参考资料
作者:酒酿小圆子~