On Sun, 09 Dec 2007 00:25:53 +0000, Jeremy C B Nicoll wrote: > > for app_name in settings.INSTALLED_APPS: > > try: > > __import__(app_name + '.management', {}, {}, ['']) > > except ImportError, exc: > > if exc.args[0]!='No module named management': > > raise ... > I want to ask a possibly related question. My impression is > that while writing and testing something like the above code one has > somehow to know that "ImportError" can be raised, so one can explicitly > define how it is to be treated. How does one find that out?
Reading the docs. Trial and error. Background knowledge about what the function is doing. There's no perfect solution; unfortunately many functions fail to document what exceptions they can be expected to raise. In principle, any exception that isn't documented is a bug. You can't be expected to recover from bugs, all you can do is report it to the function author. > While in this case, one might hope that an import action could only fail > with ImportError, isn't it possible that - say - one might get an > IOError because of a problem on the module search path ... and maybe > there are lots of other less obvious exceptions that could be raised? The author of a function has a choice to make: (1) expose any exceptions that are raised by his code to the caller; or (2) swallow those exceptions and raise one or two known exceptions. Neither is the "right" answer in all circumstances. Sometimes you might want to just propagate exceptions, especially if the caller is in a position to do something about them. Sometimes the right solution is to hide those exceptions, and just expose a single MyModuleError exception to callers. Sometimes neither is ideal. > How does one write a try/except piece of code that works (ie traps > whatever exception occurs, though obviously it can't necessarily fix an > arbitrary exception) for any exception, even those not known of in > advance by the author? Generally, you don't. If you can't recover from an exception, there's little point in trapping it. Exceptions are: (1) You're writing some sort of library function and you want to hide the internal errors that occur, so you might write: def function(): try: processing() except (IndexError, NameError): raise MyModuleError("bad things happened") except (IOError, MemoryError): raise MyModuleError("your computer is broken") (But notice how much potentially useful information you've thrown away by doing this. Are you sure you want to hide that?) (2) At the very top level of your application, where you might do something like this: # Untested if __name__ == '__main__': try: main() except (SystemExit, KeyboardInterrupt): raise except Exception, e: log_exception(e) print >>sys.stderr, "Die die die!!!" sys.exit(45) except: # Catch things that don't inherit from exceptions print >>sys.stderr, "This should never happen" sys.exit(46) Hope that helps. -- Steven. -- http://mail.python.org/mailman/listinfo/python-list