0

In all of my Python main scripts and modules, I have been trying to implement a way to log uncaught exceptions to the module in which the exception was thrown's logger. I'm doing this the same way in all of my files:

def log_unhandled_exception(*exc_info):
   text = "".join(traceback.format_exception(*exc_info))
   logger.critical("An unhandled exception has caused this script to terminate prematurely.  Here are the details: {0}".format(text))
   sys.exit(2)

def some_function():
   # ... 

sys.excepthook = log_unhandled_exception
logger = logging.getLogger("Module1") # or "Module2", "Module3", etc., each module has it's own logger

When I run into an uncaught exception, I sometimes don't get the intended logger. I think it has to do with the ordering that I import the modules: if I import module1 then import module2, and then call a function in module2 and run into an exception, it seems I get module1's logger. Conversely if I reverse the order of imports (module2 comes before module1), and I attempt the same test (exception thrown in module2), I correctly get module2's logger. I would have thought the LATER import would take precedence (overwrite the former's sys.excepthook reference), but no.

I was able to solve this problem (I guess...) by giving each logger reference a unique name in each module. So to amend the code above, THIS pattern works without regard to the order of module imports:

def log_unhandled_exception(*exc_info):
   text = "".join(traceback.format_exception(*exc_info))
   module1_logger.critical("An unhandled exception has caused this script to terminate prematurely.  Here are the details: {0}".format(text))
   sys.exit(2)

def some_function():
   # ... 

sys.excepthook = log_unhandled_exception
module1_logger = logging.getLogger("Module1") # or "Module2", "Module3", etc., each module has it's own logger

Is this the proper way to achieve my desired goal, which is for every module to have it's own logger, and every module to use it's logger to log uncaught exceptions.

(The actual code is more varied, and has a reason for every module to have their own implementation of log_unhandled_exception())

CptSupermrkt
  • 6,844
  • 12
  • 56
  • 87
  • Won't all these separate `excepthook`s stomp all over each other? If module `A` imports module `B`, module `A` will be using whatever `excepthook` came out of module `B` when the `B` import finishes. – user2357112 Dec 21 '13 at 02:13
  • Yeah that's basically what's happening, if I use the same variable names in each module. I just need some way to catch uncaught exceptions in each module, and I'm open to any design changes/ideas to accomplish this. – CptSupermrkt Dec 21 '13 at 02:55

1 Answers1

4

sys.excepthook is global for your Python process. The last value that you set to it wins. Using unique names in different files for module loggers won't have any effect on it.

jfs
  • 399,953
  • 195
  • 994
  • 1,670