如何清除Python脚本中间的所有变量?


84

我正在寻找与Matlab中的“清除”类似的东西:一种命令/函数,该命令/函数从工作区中删除所有变量,并将其从系统内存中释放出来。Python中有这样的事情吗?

编辑:我想写一个脚本,在某个时候清除所有变量。


2
如果将标题更改为“如何清除Python脚本中间的所有变量?”之类的内容,将对您有所帮助。以便将来对该主题进行搜索,因为“如何在Python中重新启动命令窗口?” 与您的实际要求无关。
山姆·多兰

您能否提供有意义的任何可能的上下文?
S.Lott

2
听起来像是另一种尝试将编码习惯从其本机环境转移到毫无意义的情况。
格伦·梅纳德

如果您只关心一些大型对象(图像或其他大型数组),则可以del在完成后使用它们。如果您只是担心名称空间混乱,则可能应该使用这么多名称重新考虑设计。例如,对于一系列图像变换,可能不需要保留每个过渡步骤。
尼克T

3
@ S.Lott:在控制台中进行探索性科学分析。通常会遇到许多不需要的变量(在尝试之后,然后确定这是不相关的途径)。但是在这种情况下,John La Rooy的答案是最合适的。
naught101'Mar

Answers:


69

以下命令序列确实从当前模块中删除了每个名称:

>>> import sys
>>> sys.modules[__name__].__dict__.clear()

我怀疑您实际上是否确实想这样做,因为“每个名称”都包含所有内置函数,因此在完全清除之后您无能为力。记住,在Python中,实际上没有“变量”之类的东西-有很多种类的对象(包括模块,函数,类,数字,字符串等),而有名称绑定到对象;该序列的作用是从模块中删除每个名称(当且仅当对它们的每个引用都已被删除时,相应的对象才会消失)。

也许您想更具选择性,但是除非您想更具体一点,否则很难准确猜测出您的意思。但是,仅举一个例子:

>>> import sys
>>> this = sys.modules[__name__]
>>> for n in dir():
...   if n[0]!='_': delattr(this, n)
... 
>>>

此序列仅保留私人名称或魔术__builtins__名称,包括包含所有内置名称的特殊名称。因此,内置程序仍然有效-例如:

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'n']
>>> 

如您所见,名称n(该变量中的控制变量for)也会碰巧缠住(因为它for每次都会在子句中重新绑定),因此最好为该控制变量命名_(例如,清楚地显示“它是特殊”(此外,在交互式解释器中,_在提示符处输入的每个完整表达式之后,名称都必须重新绑定到该表达式的值,因此不会持续很长时间;-)。

无论如何,一旦你已经确定到底是什么你想做的事,这不是很难定义的功能为目的,并把它放在你的启动文件(如果你只在互动环节希望它)或网站-自定义文件(如果您想在每个脚本中使用它)。


2
好吧,您始终可以在启动时保留原始词典的副本,然后删除已添加的名称;)但是,我认为这显然是对动态系统的滥用,因此我认为这样做并非毫无意义。英寸
monoceres

5
哈哈,这真是太棒了……令人惊讶的是,这样做会损失多少功能,而通过执行诸如以下操作可以使您获得多少功能int = (2).__class__str = ''.__class__True = (1 == 1)等...
Chinmay Kanchi

@monoceres,您将如何命名该副本以及将其隐藏在何处,以免被删除?-)
Alex Martelli 2010年

2
我越使用Python,就越喜欢它。它不仅是一门伟大的语言,而且您还可以花几个小时简单地摆弄它,并使它完成您不应该做的事情;-)
Chinmay Kanchi 2010年

1
也许我用错误的方式得到了它,但是我遇到了一个问题:当您for n in dir(): ... if n[0]!='_': delattr(this, n)在某个时候使用n=this它并在循环中将其删除时!因此,在下一次迭代中,您会尝试尝试错误,delattr(this,n)因为您刚刚将其删除!:)因此无法正常工作
Mikhail_Sam

60

不,您最好重新启动解释器

IPython是捆绑式解释器的理想替代品,并且具有%reset通常有效的命令


1
“不”是指我不应该这样做或那不可能吗?如果您说我不应该这样做,您能解释为什么吗?
snakile 2010年

6
+1:它比我第二次到四分之一花费较少ctrl-d然后pyt- >tab重新进入解释。没有理由在这里做任何事情。
山姆·多兰

3
%reset适用于大多数变量,有些则无效。对我而言,仅重新启动解释器即可保证清理所有内容。
artemis_clyde


27

如果编写函数,则一旦保留该函数,所有名称都将消失。

这个概念叫做命名空间,它是如此的好,它成为了PythonZen

命名空间是一个很棒的主意-让我们做更多这些吧!

同样,可以使用magic命令重置IPython的名称空间%reset -f。(-f意思是“强制”;换句话说,“不要问我是否真的要删除所有变量,只需执行即可。”)


我将添加一个显而易见的事实:如果将所有内容都放在一个主要功能(包括导入)中,那么您将在实践中得到一个工作场所,只需退出该功能即可重置该工作场所。我相信这确实是这个问题的目的。
戴维(David)

8
from IPython import get_ipython;   
get_ipython().magic('reset -sf')

3
请看看“如何回答
Adonis

1
或者干脆%reset -sf
सत्यमेवजयते

1
实际上,当您用anaconda提示符运行python脚本时,%reset -sf命令不起作用并引发错误(即使使用try-except也不起作用)。您可以尝试相同的方法,然后您会看到。但是,在每种可能的情况下,使用ipython库都可以解决此问题。
阿努拉格·古普塔

5

这是亚历克斯答案的修改版本。我们可以使用以下2种方法保存模块名称空间的状态并进行还原...

__saved_context__ = {}

def saveContext():
    import sys
    __saved_context__.update(sys.modules[__name__].__dict__)

def restoreContext():
    import sys
    names = sys.modules[__name__].__dict__.keys()
    for n in names:
        if n not in __saved_context__:
            del sys.modules[__name__].__dict__[n]

saveContext()

hello = 'hi there'
print hello             # prints "hi there" on stdout

restoreContext()

print hello             # throws an exception

您还可以在调用saveContext()之前添加一行“ clear = restoreContext”,并且clear()将像matlab的clear一样工作。


1
好答案!我相信对于Python 3,您需要使用来调整restoreContext names = list(sys.modules[__name__].__dict__.keys()),否则Python将抱怨您在遍历dict_keys对象时更改了字典大小。
Sam Bader

另外,对于那些想要import这个答案的人(例如,我已经保存了这个问题,并且从Jupyter笔记本中导入了这个问题,以清除作业中不同问题之间的命名空间),我想你应该使用"__main__"而不是__name__
Sam Bader

3

在Spyder中,可以为每个Python文件配置IPython控制台,以在每次执行Menu之前清除所有变量Run -> Configuration -> General settings -> Remove all variables before execution


2

globals()函数返回一个字典,其中的键是可以命名的对象的名称(顺便说一句,值是id这些对象的)。该exec()函数接受一个字符串并执行它,就像在python控制台中键入它一样。所以,代码是

for i in list(globals().keys()):
    if(i[0] != '_'):
        exec('del {}'.format(i))

尽管此代码段可以解决问题,但提供说明有助于提高响应质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
Stefan Crain

谢谢。现在好点了吗?
Kolay.Ne


0

创建包含所有必需变量的类的最简单方法不是吗?然后,您有一个包含所有curretn变量的对象,如果需要,可以覆盖此变量吗?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.