X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=bootstrap.py;h=f0fa15fb95319626552f025619ba17d76b5ec88d;hb=903843730a9916105352c729e94136a755b5e529;hp=a4923b4a9ce3424b80475c801dde8f93ed49b48f;hpb=b69d402dc503a0d38381bfa0fcd6dd5829e92775;p=python_utils.git diff --git a/bootstrap.py b/bootstrap.py index a4923b4..f0fa15f 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -3,10 +3,20 @@ # © Copyright 2021-2022, Scott Gasch """This is a module for wrapping around python programs and doing some -minor setup and tear down work for them. With it, you can break into -pdb on unhandled top level exceptions, profile your code by passing a -commandline argument in, audit module import events, examine where -memory is being used in your program, and so on. +minor setup and tear down work for them. With it, you will get: + +* The ability to break into pdb on unhandled exceptions, +* automatic support for :file:`config.py` (argument parsing) +* automatic logging support for :file:`logging.py`, +* the ability to enable code profiling, +* the ability to enable module import auditing, +* optional memory profiling for your program, +* ability to set random seed via commandline, +* automatic program timing and reporting, +* more verbose error handling and reporting, + +Most of these are enabled and/or configured via commandline flags +(see below). """ @@ -93,24 +103,24 @@ def handle_uncaught_exception(exc_type, exc_value, exc_tb): sys.__excepthook__(exc_type, exc_value, exc_tb) return else: + import io + import traceback + + tb_output = io.StringIO() + traceback.print_tb(exc_tb, None, tb_output) + print(tb_output.getvalue(), file=sys.stderr) + logger.error(tb_output.getvalue()) + tb_output.close() + + # stdin or stderr is redirected, just do the normal thing if not sys.stderr.isatty() or not sys.stdin.isatty(): - # stdin or stderr is redirected, just do the normal thing ORIGINAL_EXCEPTION_HOOK(exc_type, exc_value, exc_tb) - else: - # a terminal is attached and stderr is not redirected, maybe debug. - import io - import traceback - - tb_output = io.StringIO() - traceback.print_tb(exc_tb, None, tb_output) - print(tb_output.getvalue(), file=sys.stderr) - logger.error(tb_output.getvalue()) - tb_output.close() + else: # a terminal is attached and stderr isn't redirected, maybe debug. if config.config['debug_unhandled_exceptions']: + logger.info("Invoking the debugger...") import pdb - logger.info("Invoking the debugger...") pdb.pm() else: ORIGINAL_EXCEPTION_HOOK(exc_type, exc_value, exc_tb) @@ -203,6 +213,8 @@ for arg in sys.argv: def dump_all_objects() -> None: + """Helper code to dump all known python objects.""" + messages = {} all_modules = sys.modules for obj in object.__subclasses__(): @@ -238,8 +250,32 @@ def dump_all_objects() -> None: def initialize(entry_point): """ Remember to initialize config, initialize logging, set/log a random - seed, etc... before running main. + seed, etc... before running main. If you use this decorator around + your main, like this:: + + import bootstrap + + @bootstrap.initialize + def main(): + whatever + + if __name__ == '__main__': + main() + + You get: + + * The ability to break into pdb on unhandled exceptions, + * automatic support for :file:`config.py` (argument parsing) + * automatic logging support for :file:`logging.py`, + * the ability to enable code profiling, + * the ability to enable module import auditing, + * optional memory profiling for your program, + * ability to set random seed via commandline, + * automatic program timing and reporting, + * more verbose error handling and reporting, + Most of these are enabled and/or configured via commandline flags + (see below). """ @functools.wraps(entry_point)