[Python-Dev] PEP 343 rewrite complete

Guido van Rossum gvanrossum at gmail.com
Thu Jun 2 22:58:05 CEST 2005


[Nick Coghlan]
> Also, I'm wondering if it would be useful to have a 'closing' template
> that looked like:
> 
>    @with_template
>    def closing(obj):
>        try:
>            yield obj
>        finally:
>            obj.close()
> 
> That can be used to deterministically close anything with a close
> method, be it file, generator, or something else:
> 
>    with closing(open("argument.txt")) as contradiction:
>       for line in contradiction:
>           print line
> 
>    with closing(some_gen()) as data:
>       for datum in data:
>           process(datum)

I just realized this has a race condition. The bytecode for the
expression closing(open("...")) must necessarily contain a bytecode
that calls open() followed by another bytecode that calls closing().
If a ^C happens between these two byte codes, the stack contains an
open file object that won't be closed explicitly.

With the original opening() template, this race can be avoided (and I
intend to do so) by implementing opening() in C (as a class with
__enter__ and __exit__ methods), and by making sure that the
interpreter does *not* check for interrupts between the call to
__enter__ and the start of the try-finally-statement in the
translation of the with-statement.

The only way to avoid the race that I can see with the closing()
template would be to disable signals for the duration of the
evaluation of the expression in the with-statement, but I really don't
like that solution at all -- system calls like that can be
excruciatingly expensive compared to bytecode execution. Most
applications don't catch ^C so they don't need this extra protection
-- but the compiler doesn't know that so everybody pays for it. The
solution for avoiding interrupts between the __enter__() call and the
try start doesn't require disabling signals; there can be a single
opcode that calls __enter__ and sets up the try-finally context.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-Dev mailing list