On Mon, 11 Nov 2013 17:34:21 -0800, Victor Hooi wrote: > Hi, > > I have a general question regarding try-except handling in Python. > > Previously, I was putting the try-handle blocks quite close to where the > errors occured: > > A somewhat contrived example: > > if __name__ == "__main__": > my_pet = Dog('spot', 5, 'brown') > my_pet.feed() > my_pet.shower() > > and then, in each of the methods (feed(), shower()), I'd open up files, > open database connections etc. > > And I'd wrap each statement there in it's own individual try-except > block. (I'm guessing I should wrap the whole lot in a single try-except, > and handle each exception there?)
Your description is ambiguous. Do you mean you have: if __name__ == "__main__": try: my_pet = Dog('spot', 5, 'brown') except Whatever: pass try: my_pet.feed() except Whatever: pass try: my_pet.shower() except Whatever: pass or that each individual method has it's own try...except block? The first is certainly not good. If the call to Dog fails, you shouldn't proceed with the following lines, they certainly cannot succeed. On the other hand, if the call to my_pet.feed() fails (perhaps Spot is not hungry), then it is perfectly acceptable to ignore the exception and give Spot a bath regardless. So it depends on the circumstances. On the other hand: if __name__ == "__main__": try: my_pet = Dog('spot', 5, 'brown') my_pet.feed() my_pet.shower() except Whatever: pass is too much, since an error in feeding the dog prevents you from showing the dog. > However, the author here: > > http://stackoverflow.com/a/3644618/139137 > > suggests that it's a bad habit to catch an exception as early as > possible, and you should handle it at an outer level. Since the poster doesn't give an actual example of this, it is hard to tell what he considers too early or too late. But in general, one should only catch exceptions that you can do something about, as soon as you can do something about it. Depending on what you can do to recover from an error, that may mean wrapping each statement in it's own try block, or (more rarely, in my experience) a whole bunch of statements. > From reading other posts, this seems to be the consensus as well. > > However, how does this work if you have multiple methods which can throw > the same types of exceptions? > > For example, if both feed() and shower() above need to write to files, > when you get your IOError, how do you distinguish where it came from? You can't, at least not easily and/or portably. > (e.g. If you wanted to print a friendly error message, saying "Error > writing to file while feeding.", or if you otherwise wanted to handle it > different). If your only reason for catching the error is to suppress the stack trace and provide a "friendly" (i.e. useless) error message, then don't use try...except at all. Instead, install a customer error handler: http://docs.python.org/2/library/sys.html#sys.excepthook Otherwise, you should only catch exceptions that you can do something about. That might mean retrying the operation: while True: try: dog.feed() except DogNotHungryError: time.sleep(60*60) continue break or ignoring the failure: try: dog.feed() except DogNotHungryError: pass dog.bath() or doing something else. If you can't do anything about the error, then you shouldn't catch it, and leave it to code higher up to deal with it. > Can anybody recommend any good examples that show current best practices > for exception handling, for programs with moderate complexity? (i.e. > anything more than the examples in the tutorial, basically). Yes. Read the code in the Python standard library! Open your text editor, if possible set it to open files in read-only mode, and browse the standard library. -- Steven -- https://mail.python.org/mailman/listinfo/python-list