【问题标题】:Temporarily removing a python module暂时删除一个 python 模块
【发布时间】:2013-05-10 20:06:33
【问题描述】:

我正在尝试从 sys.modules 中临时删除一个 python 模块,以便我可以将其作为测试用例的一部分导入(模拟出各种系统功能),然后再将其放回原处。 (是的,这有点疯狂,我可能最终会重组代码而不是现在我很好奇......)

我可以删除模块并重新导入它就好了,但是一旦完成,我似乎无法将它放回原始模块。 (也许那是不可能的?)这是我写的一个测试用例来测试这个想法:

class Test(unittest.TestCase):

    def test_assumptions(self):
        import meta.common.fileutils as fu1
        del(sys.modules["meta.common.fileutils"])
        import meta.common.fileutils
        del(sys.modules["meta.common.fileutils"])
        sys.modules["meta.common.fileutils"] = fu1 # I hoped this would set the module back
        import meta.common.fileutils as fu2
        self.assertEqual(fu1, fu2)  # assert fails, fu2 is a new copy of module :-(

谁能指出它为什么会失败?

编辑,按照答案之一的建议使用 pop() 也失败了:

class Test(unittest.TestCase):

    def test_assumptions(self):
        import meta.common.fileutils as fu1
        orig = sys.modules.pop("meta.common.fileutils")
        import meta.common.fileutils
        del(sys.modules["meta.common.fileutils"])
        sys.modules["meta.common.fileutils"] = orig 
        import meta.common.fileutils as fu2
        self.assertEqual(fu1, orig) # passes
        self.assertEqual(fu2, orig) # fails
        self.assertEqual(fu1, fu2)  # fails

【问题讨论】:

  • mod1mod2 是什么?它们在哪里定义?
  • 抱歉,复制粘贴出错。我已经修好了。

标签: python python-2.7


【解决方案1】:

在我看来,这里的问题与包有关。特别是,对于存在于包中的模块(例如meta.common),有两种方法可以访问它:通过sys.modules,以及通过父包的字典(即meta.common.__dict__)。在我看来,import meta.common.fileutils as fu2 行从 meta.common.__dict__ 而不是从 sys.modules 获取 fu2 的值。

所以解决方案:除了猴子补丁 sys.modules,你还应该猴子补丁父包。即,添加如下内容:

>>> import meta.common
>>> meta.common.fileutils = fu1

就在sys.modules["meta.common.fileutils"] = fu1 行之前。

【讨论】:

    【解决方案2】:

    sys.modules 结构实际上只是一个 Python dict。您可以从中删除模块,也可以将它们放回

    将原始模块对象存储在局部变量中,使用dict.pop() 删除模块并返回它:

    orig = sys.modules.pop('meta.common.fileutils')
    

    然后,在恢复它时,只需将该对象放回sys.modules

    sys.modules['meta.common.fileutils'] = orig
    

    【讨论】:

    • 这样做也失败了,我已将更新后的代码发布为编辑。
    猜你喜欢
    • 2011-01-30
    • 2021-04-03
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 2013-12-16
    相关资源
    最近更新 更多