diff --git a/pep-0310.txt b/pep-0310.txt new file mode 100644 index 000000000..def678622 --- /dev/null +++ b/pep-0310.txt @@ -0,0 +1,194 @@ +PEP: 310 +Title: Syntax for Reliable Acquisition/Release Pairs +Version: $Revision$ +Last-Modified: $Date$ +Author: Michael Hudson , + Paul Moore +Status: Draft +Type: Standards Track +Content-Type: text/plain +Created: 18-Dec-2002 +Python-Version: 2.4 +Post-History: + + +Abstract + + It would be nice to have a less typing-intense way of writing: + + the_lock.acquire() + try: + .... + finally: + the_lock.release() + + This PEP proposes a piece of syntax (a 'with' block) and a + "small-i" interface that generalizes the above. + + +Rationale + + One of the advantages of Python's exception handling philosophy is + that it makes it harder to do the "wrong" thing (e.g. failing to + check the return value of some system call). Currently, this does + not apply to resource cleanup. The current syntax for acquisition + and release of a resource (for example, a lock) is + + the_lock.acquire() + try: + .... + finally: + the_lock.release() + + This syntax separates the acquisition and release by a (possibly + large) block of code, which makes it difficult to confirm "at a + glance" that the code manages the resource correctly. Another + common error is to code the "acquire" call within the try block, + which incorrectly releases the lock if the acquire fails. + + +Basic Syntax and Semantics + + The syntax of a 'with' statement is as follows:: + + 'with' [ var '=' ] expr ':' + suite + + This statement is defined as being equivalent to the following + sequence of statements: + + var = expr + + if hasattr(var, "__enter__"): + var.__enter__() + + try: + suite + + finally: + if hasattr(var, "__exit__"): + var.__exit__() + + If the variable is omitted, an unnamed object is allocated on the + stack. In that case, the suite has no access to the unnamed object. + + +Possible Extensions + + A number of potential extensions to the basic syntax have been + discussed on the Python Developers list. None of these extensions + are included in the solution proposed by this PEP. In many cases, + the arguments are nearly equally strong in both directions. In + such cases, the PEP has always chosen simplicity, simply because + where extra power is needed, the existing try block is available. + + Multiple expressions + + One proposal was for allowing multiple expressions within one + 'with' statement. The __enter__ methods would be called left to + right, and the __exit__ methods right to left. The advantage of + doing so is that where more than one resource is being managed, + nested 'with' statements will result in code drifting towards the + right margin. The solution to this problem is the same as for any + other deep nesting - factor out some of the code into a separate + function. Furthermore, the question of what happens if one of the + __exit__ methods raises an exception (should the other __exit__ + methods be called?) needs to be addressed. + + Exception handling + + An extension to the protocol to include an optional __except__ + handler, which is called when an exception is raised, and which + can handle or re-raise the exception, has been suggested. It is + not at all clear that the semantics of this extension can be made + precise and understandable. For example, should the equivalent + code be try ... except ... else if an exception handler is + defined, and try ... finally if not? How can this be determined + at compile time, in general? The alternative is to define the + code as expanding to a try ... except inside a try ... finally. + But this may not do the right thing in real life. + + The only use case identified for exception handling is with + transactional processing (commit on a clean finish, and rollback + on an exception). This is probably just as easy to handle with a + conventional try ... except ... else block, and so the PEP does + not include any support for exception handlers. + + +Implementation Notes + + The optional assignment in + + 'with' [ var '=' ] expr ':' + + was initially considered to be too hard to parse correctly. + However, by parsing the statement as + + 'with' expr [ '=' expr ] ':' + + and interpreting the result in the compiler phase, this can be + worked around. + + There is a potential race condition in the code specified as + equivalent to the with statement. For example, if a + KeyboardInterrupt exception is raised between the completion of + the __enter__ method call and the start of the try block, the + __exit__ method will not be called. This can lead to resource + leaks, or to deadlocks. [XXX Guido has stated that he cares about + this sort of race condition, and intends to write some C magic to + handle them. The implementation of the 'with' statement should + copy this.] + + +Open Issues + + Should existing classes (for example, file-like objects and locks) + gain appropriate __enter__ and __exit__ methods? The obvious + reason in favour is convenience (no adapter needed). The argument + against is that if built-in files have this but (say) StringIO + does not, then code that uses "with" on a file object can't be + reused with a StringIO object. So __exit__ = close becomes a part + of the "file-like object" protocol, which user-defined classes may + need to support. + + The __enter__ hook may be unnecessary - for many use cases, an + adapter class is needed and in that case, the work done by the + __enter__ hook can just as easily be done in the __init__ hook. + + If a way of controlling object lifetimes explicitly was available, + the function of the __exit__ hook could be taken over by the + existing __del__ hook. Unfortunately, no workable proposal for + controlling object lifetimes has been made so far. + + +Alternative Ideas + + IEXEC: Holger Krekel -- generalised approach with XML-like syntax + (no URL found...) + + +Backwards Compatibility + + This PEP proposes a new keyword, so the __future__ game will need + to be played. + + +References + + There are various python-list and python-dev discussions that + could be mentioned here. + + +Copyright + + This document has been placed in the public domain. + + + +Local Variables: +mode: indented-text +indent-tabs-mode: nil +sentence-end-double-space: t +fill-column: 70 +End: +