Re: [Python-Dev] PEP 340: Else clause for block statements
GvR wrote:
[Nick Coghlan]
Option 2: mimic if semantics An 'else' clause on a block statement behaves vaguely like the else clause on an if statement - the clause is executed only if the first suite is never entered, but no exception occurs (i.e. StopIteration is raised by the first call to next).
Strange because it's different from the behavior of a for loop, and the block-statement doesn't feel like an if-statement at all. But I could actually imagine a use case: when acquiring a lock with a time-out, the else-clause could be executed when the acquisition times out.
block locking(myLock, timeout=30): ...code executed with lock held... else: ...code executed if lock not acquired...
A file-closing block function has the same need, as does any block function that manages a resource, whose acquisition might fail. A surrounding try/except doesn't quite cut it; the problem is that the try-clause will then also cover the suite. Example: try: in opening('file1') as f1: ... in opening('file2') as f2: ... except IOError: print "file1 not available, I'll try again later" How do I tell try/except that I really only meant to trap opening('file1'), but opening 'file2' is not supposed to fail so I want any exception from that propagated? Better if I could write: in opening('file1') as f1: ... in opening('file2') as f2: ... else: print "file1 not available, I'll try again later" or even in opening('file1') as f1: ... in opening('file2') as f2: ... except IOError: print "file1 not available, I'll try again later" I rather like this version, because it is patently clear what should happen if there is no except-clause: The exception propagates normally. - Anders
Anders> How do I tell try/except that I really only meant to trap Anders> opening('file1'), but opening 'file2' is not supposed to fail so Anders> I want any exception from that propagated? Better if I could Anders> write: Anders> in opening('file1') as f1: Anders> ... Anders> in opening('file2') as f2: Anders> ... Anders> else: Anders> print "file1 not available, I'll try again later" -1. This has the opposite meaning of the else clause in while/for statements. Anders> or even Anders> in opening('file1') as f1: Anders> ... Anders> in opening('file2') as f2: Anders> ... Anders> except IOError: Anders> print "file1 not available, I'll try again later" Not keen on this either, maybe just because the "in" clause isn't a "try" clause. Skip
Anders J. Munch wrote:
in opening('file1') as f1: ... in opening('file2') as f2: ... except IOError: print "file1 not available, I'll try again later"
I rather like this version, because it is patently clear what should happen if there is no except-clause: The exception propagates normally.
My eyes would expect the exception handler to also catch IOErrors generated inside the block statement body. My eyes would be deceiving me, of course, but Python isn't currently so subtle and it probably shouldn't be. You could also do this with a suitable iterator. def opening_or_skipping(fn): try: f = open(fn) except IOError: print "file1 not available, I'll try again later" else: try: yield f finally: f.close() Shane
On Mon, 02 May 2005 07:46:31 -0600, Shane Hathaway <shane@hathawaymix.org> wrote:
Anders J. Munch wrote:
in opening('file1') as f1: ... in opening('file2') as f2: ... except IOError: print "file1 not available, I'll try again later"
I rather like this version, because it is patently clear what should happen if there is no except-clause: The exception propagates normally.
My eyes would expect the exception handler to also catch IOErrors generated inside the block statement body. My eyes would be deceiving me, of course, but Python isn't currently so subtle and it probably shouldn't be.
You could also do this with a suitable iterator.
def opening_or_skipping(fn): try: f = open(fn) except IOError: print "file1 not available, I'll try again later" else: try: yield f finally: f.close()
I don't think this version is really of much use. It requires that you implement a different iterator for each kind of error handling you want to do. Avoiding multiple different implementations is supposed to be one of the main selling points of this feature. Jp
[Guido, prsenting a use case]
block locking(myLock, timeout=30): ...code executed with lock held... else: ...code executed if lock not acquired...
[Anders Munch]
A file-closing block function has the same need, as does any block function that manages a resource, whose acquisition might fail.
A surrounding try/except doesn't quite cut it; the problem is that the try-clause will then also cover the suite.
Example:
try: in opening('file1') as f1: ... in opening('file2') as f2: ... except IOError: print "file1 not available, I'll try again later"
I thought of this and several other solutions overnight and didn't lik any. Finally I realized that this use case is better covered by letting the generator return an error value: def opening_w_err(filename): try: f = open(filename) except IOError, err: yield None, err else: try: yield f, None finally: f.close() The user can then write: block opening_w_err(filename) as f, err: if f: ...code using f... else: ...error handling code using err... Besides, in many cases it's totally acceptable to put a try/except block around the entire block-statement, if the exception it catches is specific enough (like IOError). For example: try: block opening(filename) as f: ...code using f... except IOError, err: ...error handling code using err... So I'm more than ever in favor of keeping the block-statement simple, i.e. without any additional clauses. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (5)
-
Anders J. Munch -
Guido van Rossum -
Jp Calderone -
Shane Hathaway -
Skip Montanaro