【问题标题】:Python memoryleak when using numpyarray in classes在类中使用 numpy 数组时的 Python 内存泄漏
【发布时间】:2019-12-18 15:24:38
【问题描述】:

我正在编写一个用于控制示波器的 python 库/包。其中一项功能是从示波器下载轨迹。数据以二进制形式发送并由 numpy 转换为浮点数。在 test_script 中,它将在(几乎)无限循环中用于保存记录的数据(当设备上没有空间时结束)。但在它耗尽空间之前,python 脚本会耗尽内存。

这是我的库的故障版本,即使被告知要释放它,它也会遇到同样的问题,即囤积内存而不释放它:

import time
import gc
import numpy
from pympler import muppy, summary

class Measurement:

    data = None

    def __del__(self):
        del self.data
        print("Deleting Measurement")

class Oscilloscope:

    def GetData(self):
        # Simulating the acquiration of the data by reading it in by a file
        p = open(r"rawdata.bin",mode="rb")
        rawdata = p.read()
        mes = Measurement()
        mes.data = numpy.array(numpy.frombuffer(bytes(rawdata), dtype='B'), dtype=float)
        p.close()
        return mes

    def __del__(self):
        print("Deleting Oscilloscope")


if __name__ == "__main__":
    myosci = Oscilloscope()
    for i in range(0,10):
        var = myosci.GetData()
        data = var.data

        # In the real script something will be done with the data
        print("Saving and evaluating Traces")
        time.sleep(0.5)

        del var
        gc.collect()
        print("Collected everything")
        # Show MemoryUsage
        all_objects = muppy.get_objects()
        sum1 = summary.summarize(all_objects)
        # Prints out a summary of the large objects
        summary.print_(sum1)
    print("Done")

执行时输出如下:

Saving and evaluating Traces
Deleting Measurement
Collected everything
                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          40 |      9.16 MB
                         str |       18144 |      3.39 MB
                        dict |        4685 |      2.21 MB
                        code |        6556 |    925.30 KB
                        type |        1060 |    868.78 KB
                       tuple |        4209 |    272.90 KB
          wrapper_descriptor |        2209 |    172.58 KB
                         set |         139 |    131.41 KB
                     weakref |        1339 |    104.61 KB
           method_descriptor |        1402 |     98.58 KB
                        list |         396 |     88.62 KB
  builtin_function_or_method |        1165 |     81.91 KB
                 abc.ABCMeta |          84 |     81.50 KB
           getset_descriptor |        1050 |     73.83 KB
                         int |        1994 |     60.12 KB
Saving and evaluating Traces
Deleting Measurement
Collected everything
                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          41 |     18.31 MB
                         str |       22639 |      3.70 MB
                        dict |        4685 |      2.21 MB
                        list |        4895 |    959.05 KB
                        code |        6556 |    925.30 KB
                        type |        1060 |    868.78 KB
                       tuple |        4212 |    273.09 KB
          wrapper_descriptor |        2209 |    172.58 KB
                         set |         139 |    131.41 KB
                     weakref |        1339 |    104.61 KB
           method_descriptor |        1402 |     98.58 KB
                         int |        2940 |     85.98 KB
  builtin_function_or_method |        1165 |     81.91 KB
                 abc.ABCMeta |          84 |     81.50 KB
           getset_descriptor |        1050 |     73.83 KB
Saving and evaluating Traces
Deleting Measurement
Collected everything
                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          42 |     27.47 MB
                         str |       27134 |      4.00 MB
                        dict |        4685 |      2.21 MB
                        list |        9392 |      1.90 MB
                        code |        6556 |    925.30 KB
                        type |        1060 |    868.78 KB
                       tuple |        4212 |    273.09 KB
          wrapper_descriptor |        2209 |    172.58 KB
                         set |         139 |    131.41 KB
                         int |        3879 |    111.66 KB
                     weakref |        1339 |    104.61 KB
           method_descriptor |        1402 |     98.58 KB
  builtin_function_or_method |        1165 |     81.91 KB
                 abc.ABCMeta |          84 |     81.50 KB
           getset_descriptor |        1050 |     73.83 KB
Saving and evaluating Traces
Deleting Measurement
Collected everything
                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          43 |     36.63 MB
                         str |       31629 |      4.31 MB
                        list |       13889 |      2.94 MB
                        dict |        4685 |      2.21 MB
                        code |        6556 |    925.30 KB
                        type |        1060 |    868.78 KB
                       tuple |        4212 |    273.09 KB
          wrapper_descriptor |        2209 |    172.58 KB
                         int |        4818 |    137.34 KB
                         set |         139 |    131.41 KB
                     weakref |        1339 |    104.61 KB
           method_descriptor |        1402 |     98.58 KB
  builtin_function_or_method |        1165 |     81.91 KB
                 abc.ABCMeta |          84 |     81.50 KB
           getset_descriptor |        1050 |     73.83 KB
Saving and evaluating Traces
Deleting Measurement
Collected everything
                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          44 |     45.78 MB
                         str |       36124 |      4.62 MB
                        list |       18386 |      4.05 MB
                        dict |        4685 |      2.21 MB
                        code |        6556 |    925.30 KB
                        type |        1060 |    868.78 KB
                       tuple |        4212 |    273.09 KB
          wrapper_descriptor |        2209 |    172.58 KB
                         int |        5757 |    163.01 KB
                         set |         139 |    131.41 KB
                     weakref |        1339 |    104.61 KB
           method_descriptor |        1402 |     98.58 KB
  builtin_function_or_method |        1165 |     81.91 KB
                 abc.ABCMeta |          84 |     81.50 KB
           getset_descriptor |        1050 |     73.83 KB
Saving and evaluating Traces
Deleting Measurement
Collected everything
                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          45 |     54.94 MB
                        list |       22883 |      5.25 MB
                         str |       40619 |      4.92 MB
                        dict |        4685 |      2.21 MB
                        code |        6556 |    925.30 KB
                        type |        1060 |    868.78 KB
                       tuple |        4212 |    273.09 KB
                         int |        6696 |    188.69 KB
          wrapper_descriptor |        2209 |    172.58 KB
                         set |         139 |    131.41 KB
                     weakref |        1339 |    104.61 KB
           method_descriptor |        1402 |     98.58 KB
  builtin_function_or_method |        1165 |     81.91 KB
                 abc.ABCMeta |          84 |     81.50 KB
           getset_descriptor |        1050 |     73.83 KB
Saving and evaluating Traces
Deleting Measurement
Collected everything
                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          46 |     64.09 MB
                        list |       27380 |      6.55 MB
                         str |       45114 |      5.23 MB
                        dict |        4685 |      2.21 MB
                        code |        6556 |    925.30 KB
                        type |        1060 |    868.78 KB
                       tuple |        4212 |    273.09 KB
                         int |        7635 |    214.36 KB
          wrapper_descriptor |        2209 |    172.58 KB
                         set |         139 |    131.41 KB
                     weakref |        1339 |    104.61 KB
           method_descriptor |        1402 |     98.58 KB
  builtin_function_or_method |        1165 |     81.91 KB
                 abc.ABCMeta |          84 |     81.50 KB
           getset_descriptor |        1050 |     73.83 KB
Saving and evaluating Traces
Deleting Measurement
Collected everything
                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          47 |     73.25 MB
                        list |       31877 |      7.85 MB
                         str |       49609 |      5.54 MB
                        dict |        4685 |      2.21 MB
                        code |        6556 |    925.30 KB
                        type |        1060 |    868.78 KB
                       tuple |        4212 |    273.09 KB
                         int |        8574 |    240.04 KB
          wrapper_descriptor |        2209 |    172.58 KB
                         set |         139 |    131.41 KB
                     weakref |        1339 |    104.61 KB
           method_descriptor |        1402 |     98.58 KB
  builtin_function_or_method |        1165 |     81.91 KB
                 abc.ABCMeta |          84 |     81.50 KB
           getset_descriptor |        1050 |     73.83 KB
Saving and evaluating Traces
Deleting Measurement
Collected everything
                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          48 |     82.40 MB
                        list |       36374 |      9.26 MB
                         str |       54104 |      5.84 MB
                        dict |        4685 |      2.21 MB
                        code |        6556 |    925.30 KB
                        type |        1060 |    868.78 KB
                       tuple |        4212 |    273.09 KB
                         int |        9513 |    265.71 KB
          wrapper_descriptor |        2209 |    172.58 KB
                         set |         139 |    131.41 KB
                     weakref |        1339 |    104.61 KB
           method_descriptor |        1402 |     98.58 KB
  builtin_function_or_method |        1165 |     81.91 KB
                 abc.ABCMeta |          84 |     81.50 KB
           getset_descriptor |        1050 |     73.83 KB
Saving and evaluating Traces
Deleting Measurement
Collected everything
                       types |   # objects |   total size
============================ | =========== | ============
               numpy.ndarray |          49 |     91.56 MB
                        list |       40871 |     10.79 MB
                         str |       58599 |      6.15 MB
                        dict |        4685 |      2.21 MB
                        code |        6556 |    925.30 KB
                        type |        1060 |    868.78 KB
                         int |       10452 |    291.39 KB
                       tuple |        4212 |    273.09 KB
          wrapper_descriptor |        2209 |    172.58 KB
                         set |         139 |    131.41 KB
                     weakref |        1339 |    104.61 KB
           method_descriptor |        1402 |     98.58 KB
  builtin_function_or_method |        1165 |     81.91 KB
                 abc.ABCMeta |          84 |     81.50 KB
           getset_descriptor |        1050 |     73.83 KB
Done
Deleting Oscilloscope

Process finished with exit code 0

即使 numpyarrays 收到删除命令并且垃圾收集器被触发,内存也会被囤积。在实际脚本中,内存使用量每一步都会增加大约 150 mB。运行我的库的 Raspberry Pi 很快就会耗尽内存。

如果你想自己测试,这里是使用的 rawdata.bin 文件: https://mega.nz/#!ps4ACAJD!0cqTJJmMU5RjSx5BqggM1afz47PqcR67hzKKnI8LgTs

【问题讨论】:

  • 如果这是 NumPy 的真正错误,您是否考虑过联系开发人员/维护人员?

标签: python numpy memory-leaks garbage-collection out-of-memory


【解决方案1】:

我不明白为什么这个内存泄漏,但我发现你可以通过添加一个来清除它

del var

您目前所在的位置

del data

如果我弄清楚这里实际发生了什么,我会更新它,这显然与data 的(多个副本)的生命周期有关。但这应该能让你启动并运行。

(你可以通过像mes.data = numpy.zeros((100,100)) 这样的操作来简化测试用例,但它仍然会泄漏)

【讨论】:

    猜你喜欢
    • 2021-05-12
    • 2013-09-28
    • 2015-01-30
    • 1970-01-01
    • 2016-03-16
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多