I agree about 'try' being another example of a, at least not immediately, flow-controlled block, I think I mentioned as much in a different response. But you're not going to win me over by saying that the #1 goal of 'with' is too best match the flow-control semantics of try|except|finally. The #1 goal, I would have hoped, was to abstract away the pattern of using try:except:finally to manage a block of code that does IO stuff. And the current 'with' doesn't even perfectly match the semantics of try|except|finally because if it did, then 'with' uses of try|except|finally that I can think of that don't have a with equivalent. try: # boilerplate while True: # boilerplate if alreadyCached(): # boilerplate break # boilerplate try: # boilerplate acquireLock() # boilerplate doSomeStuff() # <- code that does doMoreStuff() # <- stuff goes here alreadyCached(True) # boilerplate except AlreadyLocked: # boilerplate sleep() # boilerplate finally: # boilerplate cleanUpMyLockIfItExists() # boilerplate There isn't a 'with' equivalent to the above that hides all the unnecessary context state and boilerplate from the enclosed block, therefore the 'client' code must know and remember to check the appropriate flags everytime and if they don't the context's functionality may be broken. if not alreadyCached(): # <- check before we execute context block with aquireCache() as cache: ... # <- to run the ... # code they put in here with aquireCache() as cache: # <- slightly better than above if not cache: # <- but may still 'break' the context if they forget this ... # <- to run the ... # code they put in here On Feb 29, 2012, at 6:15 PM, Nick Coghlan wrote:
There are two other cases where a suite is guaranteed to at least start executing, and one of them is the only case that matters here: "try" blocks. The flow control behaviour of "with:" is consistent with the behaviour of a "try:" block, and that is not an accident.
Conditional execution of a try block requires a separate if statement or throwing an exception that is caught and suppressed by one of the exception handlers. Similarly, conditional execution of a with block requires a separate if statement or throwing an exception that is caught and suppressed by one of the context managers. Hence, arguments of language consistency aren't going to get you anywhere here.
Guido's verdict on PEP 377 was that the payoff (avoiding a separate if statement or a method call that deliberately throws an appropriate exception in certain niche use cases) wasn't worth the additional complexity in the with statement definition. I now agree with him.
Regards, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia