我正在尝试暂时从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
答案 0 :(得分:3)
sys.modules
结构实际上只是 Python dict
。您可以从中删除模块,也可以将它们放回。
将原始模块对象存储在局部变量中,使用dict.pop()
删除模块并将其返回:
orig = sys.modules.pop('meta.common.fileutils')
然后,在恢复它时,只需将该对象放回sys.modules
:
sys.modules['meta.common.fileutils'] = orig
答案 1 :(得分:3)
在我看来,这里的问题与包有关。特别是,对于存在于包中的模块(例如meta.common
),有两种方法可以访问它:via sys.modules
,并通过父包的字典(即meta.common.__dict__
) 。我认为import meta.common.fileutils as fu2
行的fu2
值来自meta.common.__dict__
,而不是来自sys.modules
。
所以解决方案:除了猴子修补sys.modules之外,你还应该修补父包。即,添加如下内容:
>>> import meta.common
>>> meta.common.fileutils = fu1
在sys.modules["meta.common.fileutils"] = fu1
行之前。