[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/) _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com