如何暂时覆盖导入行为?

How to temporarily override import behavior?

我正在使用一个模块 module_1,如果它安装在系统上,它可以使用 module_2,但如果没有,则退回到其他实现。它检查是否 module_2 的方式是:

# module_1.__init__.py

try:
    import module_2
    _MODULE2 = True
except ImportError:
    _MODULE2 = False

我在同一环境中安装了 module_2,但我不想 module_1 使用它。

有没有办法 import module_1 但覆盖 import 机制使 module_2import 专门引发 ImportError?

我尝试过的:

import sys
class hide_module_2:
    def __enter__(self):
        class HideModule2(dict):
            def __init__(self, *args, **kwargs):
                self.update(*args, **kwargs)

            def __getitem__(self, key):
                if key == 'module_2':
                    raise ImportError('Module 2 de')
                super().__getitem__(key)
        sys.modules = NoPandas(**sys.modules)

    def __exit__(self, exc_type, exc_value, traceback):
        # revert to regular dictionary
        sys.modules = dict(**sys.modules)

with hide_module_2():
    import module_1

我认为这会起作用,因为 sys.modules 是当前 imported 模块的字典,我认为它会在 import.

中引用

我能够设计出一种 hacky 解决方案,因为如果导入某些内容并且 sys.modules 中有 None,导入系统会抛出 ImportError:

class hide_module_2:   
    def __enter__(self):
        self.module_2 = sys.modules.get('module_2')
        sys.modules['module_2'] = None

    def __exit__(self, exc_type, exc_value, traceback):
        if self.module_2 is None:
          sys.modules.pop('module_2')
        else:
          sys.modules['module_2'] = self.module_2

with hide_module_2():
    import module_1