On Mon, 07 Jul 2014 20:31:53 +0300, Marko Rauhamaa wrote: > If the open() call is guarded against exceptions (as it usually should), > one must revert to the classic syntax: > > try: > f = open(path) > except IOError: > ... > try: > ... > finally: > f.close()
try: f = open(path) except Whatever: handle_error() else: with f: do_stuff() While I agree with the general idea that try blocks should be as narrow *as reasonable*, they shouldn't be as narrow *as possible* since one can start guarding against unreasonable things. try: open except NameError: ... else: try: f = open(filename) except ZeroDivisionError: # Just in case open has been monkey-patched. ... except NameError: # Oops! Forgot to bind a value to filename! # Or maybe another thread deleted open??? Woe, woe!!! ... The thing is, even if you catch these bizarre things, what are you going to do with them? If you can't do anything about it, there's no point catching the exception -- never catch anything you can't recover from, or otherwise handle. Just treat it as a fatal error and let it cause a traceback. As a general rule of thumb, if you have two things which (under reasonable circumstances) might fail in *different* ways, then it's okay to put them in the same try block, and then catch the two exceptions separately: try: do_this(with_that()) except ThatError: ... except ThisError: ... If you handle the exceptions the same way, then you can still put them in the same try block: try: do_this(with_that()) except (ThatError, ThisError): ... The worst case is when they might fail with the same exception, but you need to handle the failures differently: try: a = with_that() except ThatError: ... else: try: do_this(a) except ThatError: ... That gets old really quickly! But then, handling errors is always the ugliest part of coding. Hiding the messy details inside a function is often a good idea. -- Steven -- https://mail.python.org/mailman/listinfo/python-list