Here's the clean approach: attach additional information to the exception where it happens, and then use it in a unified place:
import os, sys def func(): try: os.mkdir('/dir') except OSError, e: if e.errno != os.errno.EEXIST: e.action = "creating directory" raise try: os.listdir('/invalid_path') except OSError, e: e.action = "reading directory" raise try: func() except Exception, e: if getattr(e, "action", None): text = "Error %s: %s" % (e.action, e) else: text = str(e) sys.exit(text)
In practice, you'd want to create wrappers for functions like mkdir and listdir if you want to do this, rather than scattering small try/except blocks all over your code.
Normally, I don't find this level of detail in error messages so important (the Python message is usually plenty), but this is a clean way to do it.