Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When/How does an anonymous file object close?

In the comments of this question about a python one-liner, it occurred to me I have no idea how python handles anonymous file objects. From the question:

open(to_file, 'w').write(open(from_file).read())

There are two calls to open without using the with keyword (which is usually how I handle files). I have, in the past, used this kind of unnamed file. IIRC, it seemed there was a leftover OS-level lock on the file that would expire after a minute or two.

So what happens to these file handles? Are they cleaned up by garbage collection? By the OS? What happens to the Python machine and file when close() is called, and will it all happen anyway when the script finishes and some time passes?

like image 689
Will Avatar asked Jul 29 '16 13:07

Will


2 Answers

Monitoring the file descriptor on Linux (by checking /proc/$$/fds) and the File Handle on Windows (using SysInternals tools) it appears that the file is closed immediately after the statement.

This cannot be guarenteed however, since the garbage collector has to execute. In the testing I have done it does get closed at once every time.

The with statement is recommended to be used with open, however the occasions when it is actually needed are rare. It is difficult to demonstrate a scenario where you must use with, but it is probably a good idea to be safe.

So your one-liner becomes:

with open(to_file, 'w') as tof, open(from_file) as fof:
    tof.write(fof.read())

The advantage of with is that the special method (in the io class) called __exit__() is guaranteed* to be called.

* Unless you do something like os._exit().

like image 78
cdarke Avatar answered Oct 20 '22 21:10

cdarke


The files will get closed after the garbage collector collects them, CPython will collect them immediately because it uses reference counting, but this is not a guaranteed behavior.

If you use files without closing them in a loop you might run out of file descriptors, that's why it's recommended to use the with statement (if you're using 2.5 you can use from __future__ import with_statement).

like image 35
Francisco Avatar answered Oct 20 '22 19:10

Francisco