#!/usr/bin/env python3
+"""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."""
+
import functools
import importlib
import logging
class ImportInterceptor(importlib.abc.MetaPathFinder):
+ """An interceptor that always allows module load events but dumps a
+ record into the log and onto stdout when modules are loaded and
+ produces an audit of who imported what at the end of the run. It
+ can't see any load events that happen before it, though, so move
+ bootstrap up in your __main__'s import list just temporarily to
+ get a good view.
+
+ """
+
def __init__(self):
import collect.trie
def repopulate_modules_by_filename(self):
self.module_by_filename_cache.clear()
- for mod in sys.modules:
- if hasattr(sys.modules[mod], '__file__'):
- fname = getattr(sys.modules[mod], '__file__')
+ for _, mod in sys.modules.copy().items(): # copy here because modules is volatile
+ if hasattr(mod, '__file__'):
+ fname = getattr(mod, '__file__')
else:
fname = 'unknown'
self.module_by_filename_cache[fname] = mod
# Maybe log some info about the python interpreter itself.
logger.debug(
- 'Platform: %s, maxint=0x%x, byteorder=%s',
- sys.platform, sys.maxsize, sys.byteorder
+ 'Platform: %s, maxint=0x%x, byteorder=%s', sys.platform, sys.maxsize, sys.byteorder
)
logger.debug('Python interpreter version: %s', sys.version)
logger.debug('Python implementation: %s', sys.implementation)
'child system: %.4fs\n'
'machine uptime: %.4fs\n'
'walltime: %.4fs',
- utime, stime, cutime, cstime, elapsed_time, walltime
+ utime,
+ stime,
+ cutime,
+ cstime,
+ elapsed_time,
+ walltime,
)
# If it doesn't return cleanly, call attention to the return value.