V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
liuxingdeyu
V2EX  ›  Python

有没有大神能解释一下为什么 Python 循环中无法释放内存

  •  
  •   liuxingdeyu · 2021-12-24 17:05:25 +08:00 · 3199 次点击
    这是一个创建于 1084 天前的主题,其中的信息可能已经有所发展或是发生改变。
    工作中遇到一个问题,启动多个 worker 去跑任务,任务是把用 bfmatch 去匹配特征点,由于图量比较大,导致一直爆内存,现在用了一个监控内存后重启进程的临时办法,然后自己写了个例子:
    while True:
    x = []
    for i in range(10000000000):
    x.append(i)
    这样内存也会很快堆起来
    然后做了这样的改动:
    while True:
    x = []
    for i in range(10000000000):
    x.append(i)
    del x
    gc.collect()
    这样内存依旧会很快堆起来
    希望有大佬能解释一下原因,顺便谁能推荐个 python 查看堆栈的工具,万分感谢
    9 条回复    2022-01-07 18:36:52 +08:00
    ch2
        1
    ch2  
       2021-12-24 17:15:28 +08:00
    先 del 再 gc.collect()内存就会回收的,内鬼可能是别的对象
    keepeye
        2
    keepeye  
       2021-12-24 17:20:08 +08:00
    del x 之后用 gc.is_finalized(x)看下是不是 True
    ipwx
        3
    ipwx  
       2021-12-24 17:22:21 +08:00
    不懂,你在循环里 del x 岂不是没用了,这循环到底干嘛的。。
    ipwx
        4
    ipwx  
       2021-12-24 17:25:32 +08:00
    In [4]: for i in range(10000000000):
    ...: if i % 10000 == 0:
    ...: del x
    ...: gc.collect()
    ...: x = []
    ...: else:
    ...: x.append(i)


    这个我验证不会爆内存
    liuxingdeyu
        5
    liuxingdeyu  
    OP
       2021-12-24 20:00:41 +08:00
    @ch2 确实是没删干净的问题,所以导致了爆内存的问题,还有就是我在做测试的时候,由于 0 过多,导致本地的内存不够用了,再加上由于某些未知的原因,没能触发 gc
    @keepeye 在 del 之后,会报错的,因为 del 后会认为这个变量没有定义
    @ipwx 这只是个例子,用来验证原因的,你这个爆报内存是因为你加了个 1 万取余数的操作大大限制了数量而且没有 while True
    ixuuux
        6
    ixuuux  
       2021-12-24 23:14:12 +08:00 via iPhone
    尝试把 del x 改为 x.clear()
    jones2000
        7
    jones2000  
       2021-12-25 12:47:23 +08:00
    把循环放到函数里面这样, 函数结束应该就会自动释放函数内使用的局部变量。

    def fun():
    x = []
    for i in range(10000000000):
    x.append(i)


    while True:
    fun()
    ipwx
        8
    ipwx  
       2021-12-25 21:08:15 +08:00
    @liuxingdeyu 好吧,那我更正我的说法。我的程序始终稳定在 0.3MB 内存不会增长。所以是删干净了
    liuxingdeyu
        9
    liuxingdeyu  
    OP
       2022-01-07 18:36:52 +08:00
    @ch2 @keepeye @ixuuux 感谢各位,最终我在我的代码中找到了问题的所在,一开始的思路跑偏了,最终发现的结果是问题出在了 multiprocessing 上,开了一堆进程,把一个大号的列表扔进去当参数,最后发现在读取处理的时候,内存会慢慢的变高,特别是把里面的内容取出来,然后从 list 转到 np.array 的时候
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4987 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 08:39 · PVG 16:39 · LAX 00:39 · JFK 03:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.