获取函数导入路径

23 投票
3 回答
24268 浏览
提问于 2025-04-15 20:15
from pack.mod import f

如何从对象 f 获取关于导入的信息 - 'pack.mod'

我可以通过 f.__module__ 来获取这个信息,但如果函数定义在我获取这个属性的模块中(f.__module__),它会返回 '__main__'。但我需要的是实际的路径 - 'pack.mod'

我找到了一种获取这个信息的方法:

inspect.getmodule(f).__file__

然后我可以从 sys.path 中减去起始路径,把 / 替换成 .,这样就能得到像 'pack.mod' 这样的路径。但可能还有更方便的方法吗?

3 个回答

0

我觉得Will上面的回答 https://stackoverflow.com/a/18712381/3166043 是不正确的,正如评论中所提到的:

cd /tmp/
mkdir test
cd test
mkdir lib
echo "class MyObject: pass" > lib/objects.py
touch lib/__init__.py
export PYTHONPATH=.
python3 -c 'import inspect; from lib.objects import MyObject; print(inspect.getmodule(MyObject).__name__)'

输出结果:

lib.objects

如果我把 from lib.objects import MyObject 替换成 from lib.objects import MyObject as MyObjectClass; MyObject = MyObjectClass(),我得到的结果是一样的。

11

你想从 __module__ 中获取 __name__ 属性:

In [16]: import inspect
In [17]: inspect.getmodule(MyObject).__name__
Out[17]: 'lib.objects.MyObject'
21

根据inspect.py的源代码inspect.getmodule(f)内部实际上做的事情是调用sys.modules.get(object.__module__)。不过,我不认为直接使用这段代码会更方便(除了“本质上”这个部分,inspect还处理了很多有用的边界情况和错误修正)。

那为什么不直接调用inspect.getsourcefile(f)呢?

编辑:从字里行间看,提问者似乎想做的是

python /foo/bar/baz/bla.py

bla.py中(这个文件作为__main__运行),想确定“从我这里,其他主脚本可以用什么fromimport语句来导入这个函数?”

问题是,这个问题提得不太好,因为可能根本没有任何可用的路径(没有什么能保证当前主脚本的路径在sys.path中,当那个不同的主脚本稍后运行时),也可能有好几条不同的路径(例如,/foo/bar/foo/bar/baz都可能在sys.path中,并且/foo/bar/baz/__init__.py存在,这样的话from baz.bla import ffrom bla import f都可能有效),而且没有什么能保证某个其他的、之前的sys.path项目不会“抢先”进行导入尝试(例如,假设/foo/bar/bazsys.path中,但在它之前还有/fee/fie/foo,而且有一个完全无关的文件/fee/fie/foo/bla.py也存在——等等等等)。

无论这种发现尝试的目的是什么,我建议寻找一种替代的架构——例如,让from baz.bla import f实际上被执行(正如提问者在问题开头所说的那样),这样f.__module__就会正确设置为baz.bla

撰写回答