首页 > Python资料 博客日记

Python查看变量及对象占用内存情况

2024-11-05 03:00:05Python资料围观29

这篇文章介绍了Python查看变量及对象占用内存情况,分享给大家做个参考,收藏Python资料网收获更多编程知识

在Python编程中,我们经常需要处理大量数据,这可能会导致内存使用量增加。了解哪些变量占用了大量内存对于优化程序性能和避免内存泄漏至关重要。本文将介绍如何在Python中查看变量及对象占用的内存大小。

在之前的文章中,我们也介绍过 基于psutil库监控程序的内存占用量 的方法,参见博客:Python 监控程序的内存占用量
其中,psutil 库可以用来获取与操作系统相关的统计信息,如CPU使用率、内存使用率、磁盘使用情况等。其提供的是整个系统的内存使用概况,而不是单个进程或对象的内存使用情况。
在本篇博客中,我们重点关注单个变量或对象占用内存的情况

1. sys.getsizeof()函数

sys.getsizeof() 是Python标准库中的一个函数,它返回的是一个对象直接占用的内存量。
这个函数对于基本数据类型(如int, str, bytes等)来说,可以给出一个准确的内存占用大小(字节数)。

使用说明:

  • sys.getsizeof()函数函数对于基本数据类型(如int, str, bytes等)来说,可以给出一个准确的内存占用大小。
  • 对于复合对象(如list, dict等),sys.getsizeof() 只会计算容器本身占用的内存,并不会包括容器中元素所占用的内存。因此,对于这样的对象,sys.getsizeof() 的结果可能并不是你想要的全部内存占用情况。

代码示例:

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 资源。 具体取决于:

  • 对象的复杂性:如果对象非常复杂,包含大量嵌套的对象或大型数据结构(如列表、字典、集合等),那么 asizeof.asizeof() 需要更多的内存和时间来处理这些对象。
  • 对象的数量:如果传递给 asizeof.asizeof() 的是一个包含大量元素的集合或列表,那么每个元素都会被递归地处理,这可能会导致较大的内存开销。
  • 递归深度:如果对象图中有深层次的嵌套,递归调用的深度会增加,这也可能导致更高的内存使用。

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 库中的一个函数,它可以递归地计算对象及其所有引用对象的内存大小。具有如下特点:

    • 递归计算:可以计算复合对象(如列表、字典)及其内部对象的内存大小。
    • 更全面:提供了比 sys.getsizeof() 更完整的内存使用信息。
    • 开销适中:相对于 @profile 装饰器来说开销较小,但仍有一定的性能影响。
  • @profile 装饰器:是 memory_profiler 库提供的功能,主要用于分析函数级别的内存使用情况。它通过跟踪函数执行期间的内存变化来提供详细的报告。具有如下特点:

    • 功能强大:可以提供详细的内存使用报告,包括函数调用期间的最大内存使用量。
    • 易于使用:只需在函数定义前加上 @profile 装饰器即可自动收集数据。
    • 开销较大:由于需要在运行时跟踪内存变化,所以可能会引入额外的性能开销。
    • 不适合实时监控:更适合于调试阶段而不是生产环境中的持续监控。

【总结分析】

  1. 如果你只需要知道单个对象的基本内存大小,并且不需要考虑对象内部引用的内存消耗,那么 sys.getsizeof() 就足够了。
  2. 如果关心的是一个复合对象及其内部结构的整体内存大小,那么 pympler.asizeof() 是最合适的选择。
  3. 如果需要了解整个函数执行期间的内存使用情况,包括最大内存使用量和详细的内存变化,那么 @profile 装饰器是合适的选择。

根据具体需求,可以选择最适合的方法来评估内存使用情况。在开发阶段,为了找到潜在的内存泄漏或者优化内存使用,这些工具都是非常有用的。

参考资料


版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐