How to close all python-opened file identifiers?

Michele Simionato michele.simionato at gmail.com
Sun Jul 27 06:58:29 CEST 2008


On Jul 26, 2:19 am, BAnderton <blake.ander... at gmail.com> wrote:
 Although I
> can't find unmatched "open" and "fid.close()" statements, I'd like to
> implement a check for open file identifiers before launching the
> editor.

So you need a debug tool to track down the opened files.
How about that:

# assume Python 2.5
from __future__ import with_statement

import __builtin__

orig_file = __builtin__.file # you could do the same for open

class ChattyFile(file):
    opened = []
    def __init__(self, *args, **kw):
        super(ChattyFile, self).__init__(*args, **kw)
        self.opened.append(self)
        print 'opened %s' % self
    def close(self):
        super(ChattyFile, self).close()
        self.opened.remove(self)
        print 'closed %s' % self

class ContextManager(object):
    def __init__(self):
        self.opened = ChattyFile.opened
    def __enter__(self):
        __builtin__.file = ChattyFile
    def __exit__(self, *exc_info):
        __builtin__.file = orig_file

chattyfile = ContextManager()

with chattyfile:
    f = file('x.txt', 'w')
    f.write('hello')
    f.close()
    file('x.txt')

print chattyfile.opened

gives:

$ python chattyfile.py
opened <open file 'x.txt', mode 'w' at 0x19df0>
closed <closed file 'x.txt', mode 'w' at 0x19df0>
opened <open file 'x.txt', mode 'r' at 0x19e48>
[<open file 'x.txt', mode 'r' at 0x19e48>]

Warning: I did not test this more than you see.
Notice also that overriding the builtins is fine
for debugging purposes (it is perhaps the only good
use case for this feature, together with testing, for mock objects).
You are expected to use it as follows:

from chattyfile import chattyfile
from mylibrary import main

with chattyfile:
   main()

and all calls to 'file' will be tracked down.
Since 'open' is basically an alias for 'file'
(they were exactly the same in Python 2.4)
you could also track 'open' in the same way.
If you are using Python 2.4 you can use the same
trick, but in a less clean way, using a try ..finally
instead of the context manager.

   Michele Simionato



More information about the Python-list mailing list