File not closed on exception
gagsl-py2 at yahoo.com.ar
Mon Oct 19 17:56:04 CEST 2009
En Mon, 19 Oct 2009 09:45:49 -0200, arve.knudsen at gmail.com
<arve.knudsen at gmail.com> escribió:
> I thought that file objects were supposed to be garbage-collected and
> automatically closed once they go out of scope, at least that's what
> I've been told by more merited Python programmers.
An object (any object) is destroyed as soon as the last reference to the
it is removed. A local variable holds a reference to the file object; it
that is the ONLY reference, the file object will be destroyed when the
variable goes out of scope, yes.
- there might be more references to the object
- garbage collection is a separate subject; objects are reference-counted,
zero=>kaputt, the GC has no say on this. GC is only used to break cycles
(a->b, b->a) that would prevent the objects to reach 0 references.
- this behavior is specific of CPython
> I'm also quite sure
> that this is quite a common assumption in various programs, at least
> given what opensource code I've seen in my time.
When an object holds references to external resources that must be freed,
this is not a good idea. Being explicit with the resource deallocation is
much better than relying on object destruction sometime in the future...
> However, the
> following script doesn't work on Windows, since the file is still open
> when I try to remove it:
> import os.path
> def create():
> f = file("tmp", "w")
> raise Exception
> try: create()
> So, what's the deal exactly, is the file supposed to be garbage-
> collected (and closed) at the end of create?
The object does not go out of scope because there is an additional
reference: the exception traceback holds a reference to all execution
frames, and each frame holds a reference to its local variables. So "f"
is still alive. This is quite good for a debugger, or for logging
purposes, as one can inspect the values of each and every variable along
the frame chain. But until exception processing is finished, the "f"
variable is alive and the "tmp" file is open.
How to deal with this depends on your use case. I don't know what can I
modify on your small example and still being representative of your actual
problem. The reccomended way to process a file uses a with statement:
with open("tmp", "w") as f:
# do something with the file
This way the file is closed when leaving the with statement (either
normally or because of an exception). And, if the file doesn't exist or
access is denied, the open() call doesn't success either. In any case, it
never remains open.
More information about the Python-list