Python 为什么我会得到;名称错误:全局名称';打开';“未定义”;在德鲁?

Python 为什么我会得到;名称错误:全局名称';打开';“未定义”;在德鲁?,python,Python,我在一个类的_del___)函数中得到一个名称错误。我不明白为什么在函数\uu del\uuu中无法访问“open”。我正在使用Python 3.4.0 Python代码: class Contoller: ... def __del__(self): store = {} ... pickle.dump(store, open('data.p', 'wb')) class MyWindow(Gtk.Window):

我在一个类的_del___)函数中得到一个名称错误。我不明白为什么在函数\uu del\uuu中无法访问“open”。我正在使用Python 3.4.0

Python代码:

class Contoller:

    ...

    def __del__(self):
        store = {}
        ...
        pickle.dump(store, open('data.p', 'wb'))    

class MyWindow(Gtk.Window):

    def __init__(self):
        ...
        self.controller = Contoller(self)
        ...
        self.connect("delete-event", self.quit)
        ...

    ...

    def quit(self, widget, event):
        del self.controller
        Gtk.main_quit()
错误消息:

Traceback (most recent call last):
  File "main.py", line 69, in __del__
NameError: name 'open' is not defined

在Python中,依靠
\uu del\uu
进行任何操作通常都不是一个好主意

最好使用一个普通的方法,并调用它,
self.controller.store()
或任何您认为最好的名称

相关讨论如

更新:atexit.register可能是您想要的。正如这篇文章在“常见错误10:误用
\uu del\uu
方法”中所描述的那样


至于解释,这个讨论告诉我们:“在解释器关闭时,在模块本身被释放之前,模块的全局变量被设置为None。”——也许这也适用于内置,我认为这只是一个范围问题

self.controller = Contoller(self)
我不知道在启动控制器类时为什么要将MyWindow类作为参数传递。尝试将其更改为:

self.controller = Contoller()

user3595184
的代码在Python 3.4之前一直有效。我知道,因为我刚刚遇到同样的问题,在
\uu del\uu
中调用
open()
。显然,内置函数不再工作,因为解释器关闭时运行
\uu del\uu
的时间发生了变化

更新: 请参阅,特别是有关终结器的部分。我有几个类封装了对资源的访问,这些资源有
\uu del\uu()
方法,可以在应用程序出于任何原因退出时解锁或清理。在应用程序级别捕获所有异常或出口并显式调用清理方法既不方便又容易出错。我将尝试改用本地
终结器

更新:
我在
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。不管如何调用,至少会调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
,这样我就可以调用所有从属对象的清理方法(
\uuuuuuuuuuuuuuuuuuuuuu。这对我很有效。

当然,这是一个解决办法。然而,这并不能解释这种行为。此外,如果存在多个实例,直接调用函数也会导致多次执行。没错,这并不能解释这种行为。然而,这不是一个解决方法,更像是一个错误修复——好吧,你真的不应该依赖于调用
\uu del\uuu
。也就是说,我对原因也有一个猜测<当您说
del
(这只是删除了对对象的引用)时,不会调用code>\uuu del\uuu
,而是在垃圾收集时调用(或者不管py impl如何工作)。当您在
del
之后在下一行退出整个应用程序时,我打赌python解释器也会开始关机等。我想在清除对象之前删除
open
之类的内置项。这不是解决方案。
weakref.finalize()
的行为类似于
atexit.register()
:擅长退出应用程序,但当它完成URI服务时,
mod_wsgi
也不会调用。我可能会查看gc.collect(),但目前我必须捕获应用程序中的所有退出路径,并显式调用清理代码。讨厌。