Improve the quick labeler again.
[python_utils.git] / bootstrap.py
index 50af84407f57e504632e868a1b1e2de32a19a671..1fcdec3de7f223230910bb24797a1bd68ca10134 100644 (file)
@@ -1,10 +1,14 @@
 #!/usr/bin/env python3
 
+# © 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."""
+memory is being used in your program, and so on.
+
+"""
 
 import functools
 import importlib
@@ -89,18 +93,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 traceback
 
-            traceback.print_exception(exc_type, exc_value, exc_tb)
+        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)
@@ -241,10 +251,16 @@ def initialize(entry_point):
         # 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__:
-            config.parse(entry_point.__globals__['__file__'])
-        else:
-            config.parse(None)
+        entry_filename = None
+        entry_descr = None
+        try:
+            entry_filename = entry_point.__code__.co_filename
+            entry_descr = entry_point.__code__.__repr__()
+        except Exception:
+            if '__globals__' in entry_point.__dict__ and '__file__' in entry_point.__globals__:
+                entry_filename = entry_point.__globals__['__file__']
+                entry_descr = entry_filename
+        config.parse(entry_filename)
 
         if config.config['trace_memory']:
             import tracemalloc
@@ -263,6 +279,10 @@ def initialize(entry_point):
         logger.debug('Python interpreter version: %s', sys.version)
         logger.debug('Python implementation: %s', sys.implementation)
         logger.debug('Python C API version: %s', sys.api_version)
+        if __debug__:
+            logger.debug('Python interpreter running in __debug__ mode.')
+        else:
+            logger.debug('Python interpreter running in optimized mode.')
         logger.debug('Python path: %s', sys.path)
 
         # Log something about the site_config, many things use it.
@@ -287,7 +307,7 @@ def initialize(entry_point):
         random.seed(random_seed)
 
         # Do it, invoke the user's code.  Pay attention to how long it takes.
-        logger.debug('Starting %s (program entry point)', entry_point.__name__)
+        logger.debug('Starting %s (program entry point)', entry_descr)
         ret = None
         import stopwatch
 
@@ -307,7 +327,7 @@ def initialize(entry_point):
             with stopwatch.Timer() as t:
                 ret = entry_point(*args, **kwargs)
 
-        logger.debug('%s (program entry point) returned %s.', entry_point.__name__, ret)
+        logger.debug('%s (program entry point) returned %s.', entry_descr, ret)
 
         if config.config['trace_memory']:
             snapshot = tracemalloc.take_snapshot()