For starters, this will help prevent the problem that you presented in your try ... finally ... example.
How did you structure it, if an exception is thrown when you try to open a file, you will never associate an open file with the name f , which will either lead to a NameError in the finally clause (if f has never been bound within the scope) or something completely unexpected ( if it is).
The correct structure (equivalent with ):
f = open(my_file) try: do_stuff_that_fails() finally: f.close()
(note - there is no need for an except clause if you have nothing to do there).
The second example is similarly incorrect and should be structured as follows:
try: f = open(my_file) try: do_stuff_that_fails() except EXPECTED_EXCEPTION_TYPES as e: do_stuff_when_it_doesnt_work() finally: f.close() except (IOError, OSError) as e: do_other_stuff_when_it_we_have_file_IO_problems()
The second (as indicated in another answer) is that you cannot forget to call f.close() .
BTW, the term "context management" rather than "resource management" - the with statement manages contexts, some of which may be resources, while others may not. For example, it is also used with decimal to create a decimal context for a specific block of code.
Finally (in response to your comment on the previous answer), you should never rely on refcount semantics to handle resources in Python. Jython, IronPython, and PyPy have non-refcount semantics, and nothing prevents CPython from going the other way (although this is unlikely for the near future). In a tight loop (for example, os.walk ) it is very easy to run out of file descriptors if the code based on refcount semantics runs on a virtual machine with different behavior.
Tim Delaney Jan 08 '12 at 2:50 2012-01-08 02:50
source share