【问题标题】:How to know who is importing me in python?如何知道谁在 python 中导入我?
【发布时间】:2011-10-24 04:32:08
【问题描述】:

如何找出在 python 中导入特定文件的文件是什么文件?

考虑以下示例:

#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 import cmn.py时,我希望运行cmn.py,cmn.py会引用b.py中定义的符号。

【问题讨论】:

  • 库不应该依赖于谁导入它们,所以这真的不重要。
  • @MichaelAaronSafyan 是对的。不过,它可以完成,正如我在这里演示的那样:stackoverflow.com/questions/7025538/…。但是...您要解决的真正问题是什么?
  • 你想达到什么目的?也许有一种替代方法可以实现它,而无需像这样耦合您的文件。
  • @Yuncy:你想让cmn.py的所有导入在cmn.py中运行一些代码吗?我问这个问题是因为正常的操作方式是 Python 只导入模块一次,所以cmn.py 通常只有一次机会知道谁在做import cmn。 Tavis Rudd 的答案可能是解决方案,如果你想抓住 every import cmn.
  • @EOL 你是对的。我想做这个。我根据反馈改进了我的问题。

标签: python import


【解决方案1】:

collections 模块中的 namedtuple 代码有一个示例,说明如何(以及何时)执行此操作:

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

【讨论】:

  • 请注意,打印语句仅在模块的第一次导入时执行。如果要捕获每个导入,则需要在每次导入后从 cmn.py 调用函数或使用导入钩子。
  • 如何为 py3 实现类似的东西?
【解决方案2】:

嗯,这是一件很奇怪的事情。你还没有解释为什么你想知道什么是导入你的模块,所以我实际上不能帮助你解决你的问题。您也没有解释如何或何时想知道导入模块。

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

【讨论】:

  • 它看起来也不能处理'import foo as bar'。
  • @TavisRudd:它确实处理了import foo as bar:who_imports(foo) 将返回执行导入的模块。这是因为测试是在module 对象上进行的(通过is module),而不是在模块名称上。请注意,报告的模块名称是原始名称(如果调用 who_imports(bar),包含导入的程序将产生名称 foo)。
  • @DietrichEpp:+1:回答问题的简洁方式。不过,who_imports() 函数可以进行优化。例如,许多sys.modules.values() 是None,可以跳过。
【解决方案3】:

您需要安装一个导入挂钩来跟踪所有导入。请参阅 PEP 302 和 http://docs.python.org/dev/py3k/library/importlib.html。但是,正如上面的 cmets 所指出的,可能有更好的方法来构建您的代码。

【讨论】:

    猜你喜欢
    • 2022-10-02
    • 2019-06-15
    • 1970-01-01
    • 2017-10-23
    • 1970-01-01
    • 2020-12-24
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多