获取函数导入路径
from pack.mod import f
如何从对象 f 获取关于导入的信息 - 'pack.mod'
我可以通过 f.__module__
来获取这个信息,但如果函数定义在我获取这个属性的模块中(f.__module__
),它会返回 '__main__'
。但我需要的是实际的路径 - 'pack.mod'
我找到了一种获取这个信息的方法:
inspect.getmodule(f).__file__
然后我可以从 sys.path
中减去起始路径,把 /
替换成 .
,这样就能得到像 'pack.mod'
这样的路径。但可能还有更方便的方法吗?
3 个回答
我觉得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()
,我得到的结果是一样的。
你想从 __module__
中获取 __name__
属性:
In [16]: import inspect
In [17]: inspect.getmodule(MyObject).__name__
Out[17]: 'lib.objects.MyObject'
根据inspect.py的源代码,inspect.getmodule(f)
内部实际上做的事情是调用sys.modules.get(object.__module__)
。不过,我不认为直接使用这段代码会更方便(除了“本质上”这个部分,inspect
还处理了很多有用的边界情况和错误修正)。
那为什么不直接调用inspect.getsourcefile(f)呢?
编辑:从字里行间看,提问者似乎想做的是
python /foo/bar/baz/bla.py
在bla.py
中(这个文件作为__main__
运行),想确定“从我这里,其他主脚本可以用什么from
或import
语句来导入这个函数?”
问题是,这个问题提得不太好,因为可能根本没有任何可用的路径(没有什么能保证当前主脚本的路径在sys.path
中,当那个不同的主脚本稍后运行时),也可能有好几条不同的路径(例如,/foo/bar
和/foo/bar/baz
都可能在sys.path
中,并且/foo/bar/baz/__init__.py
存在,这样的话from baz.bla import f
和from bla import f
都可能有效),而且没有什么能保证某个其他的、之前的sys.path
项目不会“抢先”进行导入尝试(例如,假设/foo/bar/baz
在sys.path
中,但在它之前还有/fee/fie/foo
,而且有一个完全无关的文件/fee/fie/foo/bla.py
也存在——等等等等)。
无论这种发现尝试的目的是什么,我建议寻找一种替代的架构——例如,让from baz.bla import f
实际上被执行(正如提问者在问题开头所说的那样),这样f.__module__
就会正确设置为baz.bla
。