Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting "NameError: global name 'open' is not defined" in __del__?

Tags:

I'm getting a NameError in the __del__ function of a class. I do not understand why 'open' is not accessible inside the function __del__. I am using Python 3.4.0

Python Code:

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()

Error Message:

Traceback (most recent call last):
  File "main.py", line 69, in __del__
NameError: name 'open' is not defined
like image 935
user3595184 Avatar asked May 02 '14 06:05

user3595184


2 Answers

user3595184's code used to work until Python 3.4. I know because I've just run into the same issue, calling open() within __del__. Apparently built-in functions no longer work, because of a change in when __del__ is run as the interpreter shuts down.

UPDATE: See https://docs.python.org/3/library/weakref.html, especially the section on finalizers. I have several classes that encapsulate access to resources that had __del__() methods to unlock or clean up as soon as the application would exit, for any reason. Catching all exceptions or exits at the application level and explicitly calling cleanup methods is inconvenient and bug-prone. I'll try using a local finalizer instead.

UPDATE: I'm having better luck with __enter__() and __exit__(), putting the top-level object in a with clause. It appears at least the __exit__() gets called no matter how, so I can call the cleanup methods (__exit__()'s themselves) of all subordinate objects. That's working for me.

like image 189
Quip11 Avatar answered Nov 03 '22 01:11

Quip11


It is generally not a good idea to rely on __del__ for anything in Python.

Better use a normal method and call it, self.controller.store() or whatever name you find best.

Related discussion is for example in I don't understand this python __del__ behaviour

UPDATE: atexit.register may be what you want, https://docs.python.org/2/library/atexit.html . As featured in this nice article at "Common Mistake #10: Misusing the __del__ method" http://www.toptal.com/python/top-10-mistakes-that-python-programmers-make

As for the explanation, this discussion tells: "At interpreter shutdown, the module's global variables are set to None before the module itself is released." -- perhaps that applies to builtins too, http://bugs.python.org/issue5099

like image 43
antont Avatar answered Nov 03 '22 00:11

antont