5

I m trying to do a some activity on class obj destruction. How do I achieve file open in __del__ function? (I m using Python 3.4)

class iam(object):

    def __init__(self):
        print("I m born")

    def __del__(self):
        f = open("memory_report.txt", "w")
        f.write("He gone safe")
        f.close()
    
if __name__ == '__main__':
    i = iam()
    print("Script Ends. Now to GC clean memory")


Output:

I m born
Script Ends. Now to GC clean memory
Exception ignored in: <bound method iam.__del__ of <__main__.iam object at 0x00000000022F1A58>>
Traceback (most recent call last):
  File "F:\Kumaresan\Code\Python\CommonLib\src\kmxPyQt\devConsole3\tet.py", line 14, in __del__
NameError: name 'open' is not defined    
wohlstad
  • 12,661
  • 10
  • 26
  • 39
Kaymatrix
  • 615
  • 2
  • 8
  • 16
  • 2
    Why do you want to do that? Using `__del__` at all is risky. Using it to do something like open a file is a sure road to trouble. – BrenBarn Oct 24 '14 at 08:27
  • @Jamie Bull: It might work for you but you can't rely on `__del__` being called. – Matthias Oct 24 '14 at 08:39
  • You can't rely on other resources being available when `__del__` is called if I'm reading [the docs](https://docs.python.org/2/reference/datamodel.html#object.__del__) correctly. As in OP's case where `__del__` is being called but can't find `open`. – Jamie Bull Oct 24 '14 at 08:41
  • I m using Python 3.4 – Kaymatrix Oct 24 '14 at 08:48
  • related: http://stackoverflow.com/q/6772481/674039 – wim Oct 24 '14 at 10:48

4 Answers4

3

As others have mentioned, don't use the ____del___ method to perform such cleanup. Instead, use either contextmanagers (with-statement) or register atexit-handlers.

wim
  • 338,267
  • 99
  • 616
  • 750
deets
  • 6,285
  • 29
  • 28
3

Below code is work fine.

class iam(object):

def __init__(self):
    print("I m born")

def __del__(self):
    #"open" function still in __builtins__ 
    f = open("memory_report.txt", "w")
    f.write("He gone safe")
    f.close()

def write_iam():
        i=iam()

if __name__ == '__main__':
    write_iam()
    print("Script Ends. Now to GC clean memory")

In this case:

class iam(object):

def __init__(self):
    print("I m born")

def __del__(self):
    #__builtins__.open  has remove 
    f = open("memory_report.txt", "w")
    f.write("He gone safe")
    f.close()

if __name__ == '__main__':
    i = iam()
    print("Script Ends. Now to GC clean memory")

When exit the __main__ function, before GC delete the "i" instance (execute i.__delete__) "open" function has remove from __builtins__.

MuSheng
  • 341
  • 2
  • 5
3

The problem is, as MuSheng tried to explain, that the __builtins__ are removed before your __del__ is called.

You can trigger the __del__ yourself by assigning None to the variable.

MuSheng's code could be this:

class iam():
    def __init__(self):
        print("I m born")

    def __del__(self):
        #"open" function still in __builtins__ 
        with open("memory_report.txt", "w") as f:
            f.write("He gone safe")

if __name__ == '__main__':
    i = iam()
    i = None # This triggers `__del__`
    print("Script Ends. Now to GC clean memory")

MuSheng deserves some upvotes, IMO

Community
  • 1
  • 1
GUI Junkie
  • 539
  • 1
  • 17
  • 31
2

Below is an alternate I used - Using atexit handlers:

import atexit


class iam(object):

    def __init__(self):
        print("I m born")
        atexit.register(self.cleanup)

    def cleanup(self):
        f = open("memory_report.txt", "w")
        f.write("He gone safe")
        f.close()
        print ("Done")


if __name__ == '__main__':
    i = iam()
    print("Script Ends. Now to GC clean memory")

Output:

I m born
Script Ends. Now to GC clean memory
Done
Kaymatrix
  • 615
  • 2
  • 8
  • 16