Post Import Hooks In Python 3
Solution 1:
I would be shocked to find out that this is the best way to do this ... However, since early python2.x versions, monkey patching __import__
has been supported. We can take advantage of that here:
try:
import builtins # python3.xexcept ImportError:
import __builtin__ as builtins # python2.ximport sys
import collections
_builtin_import = builtins.__import__def_my_import(name, globals=None, locals=None, fromlist=(), level=0):
already_imported = name in sys.modules
mod = _builtin_import(
name,
globals=globals,
locals=locals,
fromlist=fromlist,
level=level)
ifnot already_imported and name in _post_import_hooks:
for hook in _post_import_hooks[name]:
hook()
return mod
builtins.__import__ = _my_import
_post_import_hooks = collections.defaultdict(list)
defon_import(name):
defdecorator(func):
_post_import_hooks[name].append(func)
return func
return decorator
@on_import('numpy')defprint_hi():
print('Hello Numpy')
print('before numpy')
import numpy
print('after numpy')
This answer makes a super simple registry for registering callbacks. The decorator just registers the function and then returns it. It doesn't do any fancy checking (for whether the module is already loaded, for example), but could easily be extended to do that.
Obviously the downside is if some other module decides to monkey patch __import__
, then you're out of luck -- Either this module or the other one is likely to end up broken.
I've tested this and it seems to work on both python2.x and python3.x.
Solution 2:
The wrapt
module provides an implementation of this.
Watch this video about wrapt
, including this feature:
Don't think the documentation for wrapt
mentions it yet.
Some of the blogs posts at end of:
talk about it though.
There is a companion module for wrapt
called autowrapt
which allows you to do monkey patching using this mechanism without needing to change the application code itself to trigger it.
Solution 3:
Does this work?
import importlib
classImportHook:
def__init__(self, func):
self.func = func
self.module = Nonedef__enter__(self):
return self
defget_module(self, module_name):
self.module = importlib.import_module(module_name)
return self.module
def__exit__(self, exc_type, exc_val, exc_tb):
if self.module isnotNone:
self.func(self.module)
defset_linewidth(module):
import shutil
module.set_printoptions(linewidth=shutil.get_terminal_size()[0])
with ImportHook(set_linewidth) as hook:
numpy = hook.get_module('numpy')
Post a Comment for "Post Import Hooks In Python 3"