如何记录在代码块中执行的所有导入?

时间:2012-09-17 22:19:53

标签: python

我正在编写测试套件,我正在测试的代码过度使用延迟模块导入。因此,对于相同方法的5个不同输入,这可能最终导入5个额外模块。我希望能够做的是设置测试,以便我可以断言用一个输入运行方法会导致一次导入,而不会导致另一个导入。

我有一些关于如何开始这个的想法,但到目前为止都没有成功。我已经有了一个自定义导入器,我可以将日志代码放入导入器中。但这不起作用,因为import语句只运行一次。无论先前是否已导入模块,我都需要执行日志语句。只运行del sys.modules['modname']也不起作用,因为它在测试代码中运行,我无法在正在测试的代码中重新加载模块。

我尝试的下一件事是继承dict来进行监控,并用这个子类替换sys.modules。此子类具有重新实现的__getitem__方法,但调用import module似乎不会触发子类中的__getitem__调用。我也无法直接分配给sys.modules.__getitem__,因为它是只读的。

我正在尝试做什么?

更新

nneonneo的答案似乎只有在logImports()的实现与使用它的模块相同时才有效。如果我创建一个包含此功能的基础测试类,则会出现问题。第一个是它找不到__import__,错误地用:

#     old_import = __import__
# UnboundLocalError: local variable '__import__' referenced before assignment

当我将其更改为__builtin__.__import__时,我又出现了另一个错误:

myunittest.py:

import unittest
class TestCase(unittest.TestCase):
    def logImports(self):
        old_import = __builtins__.__import__
        def __import__(*args, **kwargs):
            print args, kwargs
            return old_import(*args, **kwargs)

        __builtins__.__import__ = __import__

test.py:

import myunittest
import unittest
class RealTest(myunittest.TestCase):
    def setUp(self):
        self.logImports()
    def testSomething(self):
        import unittest
        self.assertTrue(True)
unittest.main()

#     old_import = __builtins__.__import__
# AttributeError: 'dict' object has no attribute '__import__'

2 个答案:

答案 0 :(得分:3)

尝试

old_import = __import__
def __import__(*args, **kwargs):
    print args, kwargs
    return old_import(*args, **kwargs)

__builtins__.__import__ = __import__

这会完全覆盖__import__,允许您监控import的每次调用。

答案 1 :(得分:-1)

基于上一个答案,在 Python 3 中,我在以下方面取得了成功。

    var SS = SpreadsheetApp.getActiveSpreadsheet();
    var ss = SS.getSheetByName('Volunteers');
    var urlVol = '';
    urlVol += SS.getUrl();
    urlVol += '#gid=';
    urlVol += ss.getSheetId(); 
    return urlVol; 
  }