I have a script that instantiates a number of child objects. When the script (and these objects) end...the objects need to do a little cleanup (especially temp file close and delete).
I keep reading how __del__
is unreliable - however a context manage does not appear to work a the child objects will not persist. They need to hang around (to do things like file reads and writes)
An example:
WRITER.PY
import os
class Writer(object):
def __init__(self, filename):
self.filename = filename
self.open()
def open(self):
self.fh = open(self.filename, "w+", 0)
def write(self, msg):
print >>self.fh, str(msg)
def close(self):
self.fh.close()
os.remove(self.filename)
def __enter__(self):
print "entered"
# self.open()
def __exit__(self, type, value, traceback):
print "__exit__"
self.close()
MAIN.PY
def myfunc(filename):
with WRITER.Writer(filename) as writeit:
# do some stuff
writeit.write("hallo")
# do some more stuff
writeit.write("more results")
# even more stuff
writeit.write("goodbye")
But when I run myfunc()
, the object is garbage collected as soon as it finishes the __init__()
. It goes straight from enter to exit and performs none of the duties after the with statement. It doesn't seem to matter if I put the open in the __init__
or the __enter__
.
OUTPUT:
Traceback (most recent call last):
File "/shared/GitHub/Tesera/MRAT_Refactor/bin/MAIN.py", line 13, in <module>
myfunc("./tempfile")
File "/shared/GitHub/Tesera/MRAT_Refactor/bin/MAIN.py", line 6, in myfunc
writeit.write("hallo")
AttributeError: 'NoneType' object has no attribute 'write'
entered
__exit__
Is there a way to use a context manager in this way, a better way to use __del__
...or is there a third option to accomplish this?
The problem has nothing to do with garbage collection. As documented, the as
clause binds the return value of the __enter__
method. You aren't returning anything, so you get None.
If you want the Writer
object to be returned, you need to do return self
at the end of the __enter__
method.