如何知道谁在导入我?
我怎么才能知道哪个文件在导入某个特定的文件呢?
考虑下面这个例子:
#a.py
import cmn
....
#b.py
import cmn
...
#cmn.py
#Here, I want to know which file (a.py or b.py)
#is importing this one.
#Is it possible to do this?
...
所有的文件 a.py
、b.py
和 cmn.py
都在同一个文件夹里。
我为什么想知道这个?
在C/C++中,他们有一个叫做包含的功能。我想做的事情可以通过C/C++的代码来说明。
//a.cpp
....
#define SOME_STUFF ....
#include "cmn.h"
//b.cpp
...
#define SOME_STUFF ....
#include "cmn.h"
//cmn.h
//Here, I'll define some functions/classes that will use the symbol define
//in the a.cpp or b.cpp
...
....code refer to the SOME_STUFF.....
在C/C++中,我们可以用这种方法来重用源代码。
现在回到我的Python代码。
当 a.py
导入 cmn.py
时,我希望运行 cmn.py
,并且 cmn.py
会引用在 a.py
中定义的符号。
当 b.py
导入 cmn.py
时,我希望运行 cmn.py
,并且 cmn.py
会引用在 b.py
中定义的符号。
3 个回答
1
你需要安装一个导入钩子,这个钩子可以跟踪所有的导入操作。可以参考PEP 302和这个链接了解更多。不过,正如上面的评论所提到的,可能有更好的方法来组织你的代码。
3
嗯,这个问题有点奇怪。你没有解释清楚你为什么想知道是哪个模块在导入你的模块,所以我其实没法帮你解决这个问题。你也没有说明你想在什么情况下或者什么时候知道这个导入模块。
def who_imports(studied_module):
for loaded_module in sys.modules.values():
for module_attribute in dir(loaded_module):
if getattr(loaded_module, module_attribute) is studied_module:
yield loaded_module
这个方法会给你一个迭代器,列出所有把你的模块当作顶层对象使用的模块。不过,它找不到那些用 from cmn import *
这种方式导入的模块,而且这个列表会随着时间的推移而变化。
>>> import os
>>> for m in who_imports(os):
... print m.__name__
...
site
__main__
posixpath
genericpath
posixpath
linecache
12
namedtuple 是 collections 模块中的一段代码,它给出了如何(以及何时)使用这个功能的例子:
#cmn.py
import sys
print 'I am being imported by', sys._getframe(1).f_globals.get('__name__')
这种方法有一个限制,就是最外层的模块总是叫做 __main__
。如果是这样的话,可以通过 sys.argv[0]
来确定最外层模块的名字。
第二个限制是,如果使用 sys._getframe
的代码在模块的范围内,它只会在第一次导入 cmn.py
时执行。如果你想监控模块的所有导入,就需要在导入后调用某个函数。