Package: border-patrol
Border-PatrolBorder-Patrol logs all imported packages and their version to support you while debugging. In 95% of all cases when
something suddenly breaks in production it is due to some different version in one of your requirements. Pinning down the
versions of all your dependencies and dependencies of dependencies inside a virtual environment helps you to overcome
this problem but is quite cumbersome and thus this method is not always applied in practice. Also sometimes, like when
you are using PySpark, you might not be 100% sure which library versions are installed on some cluster nodes.With Border-Patrol you can easily find the culprit by looking in the logs of the last working version and compare it
to the failing one since Border-Patrol will list all imported packages and their corresponding version right at the
end of your application, even if it crashed.UsageBorder-Patrol is really simple to use, just install it withpip install border-patroland import it before any other package, e.g.:fromborder_patrolimportwith_print_stdoutimportpandasaspdIf you run those lines in a script, you will get a similar output to this one:Python version is 3.6.7 |Anaconda, Inc.| (default, Oct 23 2018, 14:01:38)[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]Following packages were imported:PACKAGE         VERSION   PATHborder_patrol   0.1       /Users/fwilhelm/Sources/border_patrol/src/border_patrolcycler          0.10.0    /Users/fwilhelm/anaconda/envs/lib/python3.6/site-packages/cycler.pydateutil        2.7.5     /Users/fwilhelm/anaconda/envs/lib/python3.6/site-packages/dateutil/__init__.pymatplotlib      2.2.3     /Users/fwilhelm/anaconda/envs/lib/python3.6/site-packages/matplotlib/__init__.pynumpy           1.15.1    /Users/fwilhelm/anaconda/envs/lib/python3.6/site-packages/numpy/__init__.pypandas          0.23.4    /Users/fwilhelm/anaconda/envs/lib/python3.6/site-packages/pandas/__init__.pypyparsing       2.3.0     /Users/fwilhelm/anaconda/envs/lib/python3.6/site-packages/pyparsing.pypytz            2018.7    /Users/fwilhelm/anaconda/envs/lib/python3.6/site-packages/pytz/__init__.pysix             1.11.0    /Users/fwilhelm/anaconda/envs/lib/python3.6/site-packages/six.pyIf you importwith_print_stdout, Border-Patrol will useprintas output function whereaswith_print_stderrwill
print to standard error. Since most production applications will rather use theloggingmodule, you can tell
Border-Patrol to use it by importingwith_log_{error|warning|info|debug}.
For instancefrom border_patrol import with_log_infowill log the final report by using theINFOlogging level.If you want even more fine grained control you can import theBorderPatrolclass directly from theborder_patrolpackage
and use theregister()andunregister()method to activate and deactivate it, respectively. At any point the
tracking can be circumvented by usingborder_patrol.builtin_import.How does it work?Border-Patrol is actually quite simple. It overwrites the__import__function in Python'sbuiltinspackage to track
every imported module. For each module the corresponding package is determined and the version number is retrieved with
the help of the__version__attribute which most professional libraries provide at the package level. If this fails
the distribution name for the package is determined, e.g.scikit-learnis the distribution containing thesklearnpackage,
with the help ofpkg_resourceswhich is a part ofsetuptools. Then the distribution name is used to determine the
version number also usingpkg_resources, similar to howpipwould do it.Finally, Border-Patrol registers anatexithandler to be called when your application finishes and
reports all imported modules. To avoid any problem registering these things more than once, Border-Patrol is implemented
as a singleton and thus it isnotthread-safe.NoteThis project has been set up using PyScaffold 3.1. For details and usage information on PyScaffold seehttps://pyscaffold.org/.