如何知道谁在导入我?

12 投票
3 回答
2896 浏览
提问于 2025-04-17 04:52

我怎么才能知道哪个文件在导入某个特定的文件呢?

考虑下面这个例子:

#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.pyb.pycmn.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

namedtuplecollections 模块中的一段代码,它给出了如何(以及何时)使用这个功能的例子:

#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 时执行。如果你想监控模块的所有导入,就需要在导入后调用某个函数。

撰写回答