【问题标题】:Is there a way to delete created variables, functions, etc from the memory of the interpreter?有没有办法从解释器的内存中删除创建的变量、函数等?
【发布时间】:2014-12-20 02:56:08
【问题描述】:

我这几天一直在寻找这个问题的准确答案,但没有得到任何好的结果。我不是一个完全的编程初学者,但还没有达到中级水平。

当我在 Python 的 shell 中,我输入:dir(),我可以看到当前作用域(主块)中所有对象的所有名称,其中有 6 个:

['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

然后,当我声明一个变量时,例如x = 10,它会自动添加到内置模块dir()下的对象列表中,当我再次输入dir()时,它现在显示:

['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'x']

函数、类等也是如此。

如何删除所有这些新对象而不删除开始时可用的标准 6?

我在这里读过“内存清理”、“控制台清理”,它会清除命令提示符窗口中的所有文本:

>>> import sys
>>> clear = lambda: os.system('cls')
>>> clear()

但这一切都与我想要实现的目标无关,它不会清除所有使用过的对象。

【问题讨论】:

  • 为什么你觉得你需要这样做,或者你只是出于好奇?
  • 我只是不知道那里有一个del 函数。我开始学习 Python 并且经常需要在 shell 中进行实验,因此标准变量名称(如 xy)通常已经在使用中,并且重新启动 shell 需要另外 15 秒(我有一个非常非常现在的旧笔记本电脑)。所以我想找到一种更快清理 Python 内存的方法。
  • 啊。 FWIW,del 不完全是一个函数,因此没有()。这是一个引入 del 语句的关键字。当然,它实际上如何删除一个对象可能涉及到函数,但那是另一回事了……
  • 在 shell 中试验时,不应使用 xy 等名称,除非正在使用它们。或者除非你做一些像from _somemodule_ import * 这样的傻事,否则你会得到各种各样的垃圾。 :)
  • 我用谷歌搜索了这个问题,现在我想知道 - 如果我想删除所有变量和函数,为什么不能重新启动内核并从顶部重新运行脚本?

标签: python memory-management dir


【解决方案1】:

您可以使用del删除个人姓名:

del x

或者您可以将它们从globals() 对象中删除:

for name in dir():
    if not name.startswith('_'):
        del globals()[name]

这只是一个示例循环;它防御性地仅删除不以下划线开头的名称,并做出(并非不合理的)假设,即您仅在解释器的开头使用了没有下划线的名称。如果您真的想要彻底,您可以使用硬编码的名称列表来保留(白名单)。除了退出并重新启动解释器之外,没有内置函数可以为您进行清除。

您已导入的模块 (import os) 将保持导入状态,因为它们被 sys.modules 引用;后续导入将重用已导入的模块对象。您只是不会在当前的全局命名空间中引用它们。

然而,Python 不对内存中的数据做出任何安全保证。当不再引用对象时,解释器将内存标记为不再使用,但不会采取措施覆盖该内存以防止访问数据。如果您需要这种级别的安全保护,则需要使用第三方扩展来管理自己的内存并考虑安全性。

【讨论】:

  • 好吧,我不得不说startswith('_') 似乎很幼稚。如果有人聪明到可以写_foo=42 甚至__foo__=42,我们如何删除这些?有没有办法以编程方式获取标准模块属性的名称?
  • @georg:我已经对循环进行了防御性编码。如果你想做得更好,你必须硬编码一个初始的名字列表。
  • 那么,不行吗?我的想法是dir(ModuleType()),但它只返回docname
  • @georg:不;解释器的全局命名空间也因版本而异,并且没有万无一失的方法(据我所知)来枚举当您在稍后阶段打开解释器时其中的内容。
  • @nakE 函数和类只是对象,就像任何其他对象一样。它们并不特别;使用白名单或检查您需要保留类和函数的对象类型。
【解决方案2】:

这应该可以解决问题。

globals().clear()

【讨论】:

  • 添加一行说明为什么会这样会很有帮助!
  • 这是唯一适用于基本 python shell 的建议。
【解决方案3】:

这对我有用。

你需要为全局变量运行两次,然后是本地变量

for name in dir():
    if not name.startswith('_'):
        del globals()[name]

for name in dir():
    if not name.startswith('_'):
        del locals()[name]

【讨论】:

  • locals()得到的字典对象没有办法修改,所以在上面使用del也是无效的。
【解决方案4】:

你可以使用python垃圾收集器:

import gc
gc.collect()

【讨论】:

  • 嘿@Fardin!谢谢!您的回答完成了工作并挽救了我的一天!但在 gc.collect() 之前我做了 del(variable)。
  • gc.collect() 本身不起作用。像上面提到的Gmosy一样,必须使用del(变量名)。
  • gc.collect() 似乎什么也没做。所有变量仍然可以访问。
【解决方案5】:

如果您处于 Jupyteripython 之类的交互式环境中,您可能有兴趣清除不需要的 var (如果它们越来越重)。

魔术命令 resetreset_selective 可用于交互式 Python 会话,例如 ipythonJupyter

1) reset

reset 如果不带参数调用,则通过删除用户定义的所有名称来重置命名空间。

inout 参数指定是否要刷新输入/输出缓存。使用dhist 参数刷新目录历史记录。

reset in out

另一个有趣的是array,它只删除了 numpy 数组:

reset array

2)reset_selective

通过删除用户定义的名称来重置命名空间。 输入/输出历史记录会留下来以备不时之需。

清理数组示例:

In [1]: import numpy as np
In [2]: littleArray = np.array([1,2,3,4,5])
In [3]: who_ls
Out[3]: ['littleArray', 'np']
In [4]: reset_selective -f littleArray
In [5]: who_ls
Out[5]: ['np']

来源:http://ipython.readthedocs.io/en/stable/interactive/magics.html

【讨论】:

    【解决方案6】:

    是的。有一种简单的方法可以删除 iPython 中的所有内容。 在 iPython 控制台中,只需键入:

    %reset
    

    然后系统会要求您确认。按 y。 如果您不想看到此提示,只需键入:

    %reset -f
    

    这应该可行..

    【讨论】:

    • 再一次,为什么这不是最佳答案?
    • @myradio 因为它与不使用IPython 的每个人都无关,而且它也不能回答问题;该问题询问如何删除全局对象引用,而不是重置 IPython shell 的内容。
    • 这是我在 Jupyter Notebook 中寻找的用于在不重新启动内核的情况下清除变量(以释放 CPU/GPU Ram)的神奇命令!
    【解决方案7】:

    实际上python会回收不再使用的内存。这称为垃圾收集,这是python中的自动过程。但是,如果您想这样做,则可以通过del variable_name 将其删除。您也可以通过将变量分配给None 来做到这一点

    a = 10
    print a 
    
    del a       
    print a      ## throws an error here because it's been deleted already.
    

    真正从未引用的 Python 对象中回收内存的唯一方法是通过垃圾收集器。 del 关键字只是将名称与对象解除绑定,但该对象仍需要进行垃圾回收。您可以使用 gc 模块强制垃圾收集器运行,但这几乎可以肯定是一种过早的优化,但它有其自身的风险。使用 del 没有实际效果,因为这些名称无论如何都会被删除,因为它们超出了范围。

    【讨论】:

    • 确实如此。当然,在解释器的全局命名空间中工作时,名称不会超出范围,但那又如何。 :) 我想还值得一提的是,已被垃圾回收的对象所使用的内存所发生的事情是依赖于实现的,但在大多数 Python 实现中,gc'ed 内存只是回到 Python 池,它不是 在程序退出之前返回操作系统。
    • @PM2Ring LOL :) 我想是的。你从哪里提到python?
    • 请注意,在 CPython 中,GC 只需要中断引用循环。如果没有保留引用,则将对象 从内存中立即删除。所以del确实在这里有真正的效果。
    • @MartijnPieters,已删除?这是一个技术术语吗? :)
    • @eryksun:当然,正如 RFC 4042-bis2 所定义的那样! :-P
    猜你喜欢
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-04
    • 2017-02-12
    • 2017-05-18
    • 1970-01-01
    相关资源
    最近更新 更多