X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=bootstrap.py;h=bf5d91f9eb3a42cd2432d493b74aba436e85e640;hb=4c315e387f18010ba0b5661744ad3c792f21d2d1;hp=7f63dbb52259375305730f8adc952b2766b71a53;hpb=83c1e0d04fe2e78963c8b508e8b7d0ae03bfcb16;p=python_utils.git diff --git a/bootstrap.py b/bootstrap.py index 7f63dbb..bf5d91f 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -42,6 +42,11 @@ original_hook = sys.excepthook def handle_uncaught_exception(exc_type, exc_value, exc_tb): + """ + Top-level exception handler for exceptions that make it past any exception + handlers in the python code being run. Logs the error and stacktrace then + maybe attaches a debugger. + """ global original_hook msg = f'Unhandled top level exception {exc_type}' logger.exception(msg) @@ -57,11 +62,11 @@ def handle_uncaught_exception(exc_type, exc_value, exc_tb): # stdin or stderr is redirected, just do the normal thing original_hook(exc_type, exc_value, exc_tb) else: - # a terminal is attached and stderr is not redirected, debug. + # a terminal is attached and stderr is not redirected, maybe debug. + import traceback + traceback.print_exception(exc_type, exc_value, exc_tb) if config.config['debug_unhandled_exceptions']: - import traceback import pdb - traceback.print_exception(exc_type, exc_value, exc_tb) logger.info("Invoking the debugger...") pdb.pm() else: @@ -69,12 +74,21 @@ def handle_uncaught_exception(exc_type, exc_value, exc_tb): def initialize(entry_point): + """ + Remember to initialize config, initialize logging, set/log a random + seed, etc... before running main. - """Remember to initialize config and logging before running main.""" + """ @functools.wraps(entry_point) def initialize_wrapper(*args, **kwargs): + + # Hook top level unhandled exceptions, maybe invoke debugger. if sys.excepthook == sys.__excepthook__: sys.excepthook = handle_uncaught_exception + + # Try to figure out the name of the program entry point. Then + # parse configuration (based on cmdline flags, environment vars + # etc...) if ( '__globals__' in entry_point.__dict__ and '__file__' in entry_point.__globals__ @@ -83,8 +97,9 @@ def initialize(entry_point): else: config.parse(None) + # Initialize logging... and log some remembered messages from + # config module. logging_utils.initialize_logging(logging.getLogger()) - config.late_logging() # Allow programs that don't bother to override the random seed @@ -102,8 +117,8 @@ def initialize(entry_point): logger.debug(msg) random.seed(random_seed) + # Do it, invoke the user's code. Pay attention to how long it takes. logger.debug(f'Starting {entry_point.__name__} (program entry point)') - ret = None import stopwatch with stopwatch.Timer() as t: @@ -121,6 +136,8 @@ def initialize(entry_point): f'child system: {cstime}s\n' f'machine uptime: {elapsed_time}s\n' f'walltime: {walltime}s') + + # If it doesn't return cleanly, call attention to the return value. if ret is not None and ret != 0: logger.error(f'Exit {ret}') else: