是否有可能以某种方式覆盖import
,以便我可以在导入之前对模块执行更复杂的操作?
作为示例:我有一个更大的应用程序,它使用matplotlib
作为对应用程序的整体功能不重要的辅助功能。如果未安装matplotlib
,我只想模拟功能,以便导入和对matplotlib
函数的所有调用似乎都有效,只是没有实际做任何事情。然后,一个简单的警告应该表明模块没有安装,尽管这个事实不会损害应用程序的核心功能。我已经有一个导入函数,在没有安装matplotlib
的情况下,返回一个MagicMock
对象而不是实际模块,它只是模仿matplotlib
API的行为。
因此,所有import matplotlib...
或from matplotlib import...
应该被相应的函数调用自动覆盖。我可以手动替换所有import
和from ... import
表达式,但我想制作,但有很多。我希望通过覆盖import
来自动拥有此功能。
这可能吗?
答案 0 :(得分:2)
我发现的最简单方法是将__import__
函数替换为您自己的实现(描述为here)。然后,如果有人试图导入matplotlib
,您只需导入另一个模块:
def _import(name, *args, **kwargs):
if name == 'matplotlib': # if someone tries to import matplotlib...
name = 'my_mocked_matplotlib' # ...import the mocked version instead
return original_import(name, *args, **kwargs)
import builtins
original_import = builtins.__import__
builtins.__import__ = _import
要将自定义导入行为限制为仅限几个模块,您可以使用内省(使用inspect module)找出导入执行的模块:
import inspect
def _import(name, *args, **kwargs):
if name == 'matplotlib': # if someone tries to import matplotlib...
# find out which module is performing the import
frame = inspect.currentframe().f_back
module_path = frame.f_globals['__file__']
# if the import is happening in module1 or module2, redirect it
if module_path in ('/path/to/module1.py','/path/to/module2.py'):
name = 'my_mocked_matplotlib' # ...import the mocked version instead
return original_import(name, *args, **kwargs)
答案 1 :(得分:0)
简短回答是否 ......但是当模块不存在时,你可以而且应该抓住ImportError
,然后处理它。否则用其他东西替换所有import语句是很聪明的事情。