在Python中查找模块路径而不导入
我看到过几种方法可以通过先导入一个模块来找到它的路径。有没有办法在不导入模块的情况下找到这个路径呢?
5 个回答
1
对于大多数使用场景,其实你不需要依赖第三方的帮助。importlib.util.find_spec
从 Python 3.4 开始就已经存在了,它可以解决顶层导入的问题:
>>> import importlib.util
>>> spec = importlib.util.find_spec("foo")
>>> spec.origin
/home/me/my_venv/python3.11/site-packages/foo/__init__.py
还有一个便携的版本,可以获取父文件夹:
[...]
>>> from pathlib import Path
>>> Path(spec.origin).parent
/home/me/my_venv/python3.11/site-packages/foo
注意事项:
- 对于子包(比如
foo.bar
),父包会被实际导入。由于 Python 的动态特性,包括导入的解析方式,没有一种正确的解决方案可以不进行实际导入(比如,试着找到os.path
的位置,但不导入os
,这就是一个真实的例子)。 - 如果包不存在,
spec
的值会是None
。 - 如果这个包实际上是一个命名空间,
spec.origin
的值也会是None
。
16
在Python 3中,imp
这个模块已经不推荐使用了。你可以使用pkgutil(就像上面提到的那样),或者如果你使用的是Python 3.4及以上版本,可以使用importlib.util.find_spec来代替:
>>> import importlib
>>> spec = importlib.util.find_spec("threading")
>>> spec.origin
'/usr/lib64/python3.6/threading.py'
71
使用 pkgutil 模块:
>>> import pkgutil
>>> package = pkgutil.get_loader("pip")
>>> package.filename
'/usr/local/lib/python2.6/dist-packages/pip-0.7.1-py2.6.egg/pip'
>>> package = pkgutil.get_loader("threading")
>>> package.filename
'/usr/lib/python2.6/threading.py'
>>> package = pkgutil.get_loader("sqlalchemy.orm")
>>> package.filename
'/usr/lib/pymodules/python2.6/sqlalchemy/orm'
在 Python 3 中,可以用 pkgutil.get_loader("模块名称").get_filename()
来代替。
使用 imp 模块:
>>> import imp
>>> imp.find_module('sqlalchemy')
(None, '/usr/lib/pymodules/python2.6/sqlalchemy', ('', '', 5))
>>> imp.find_module('pip')
(None, '/usr/local/lib/python2.6/dist-packages/pip-0.7.1-py2.6.egg/pip', ('', '', 5))
>>> imp.find_module('threading')
(<open file '/usr/lib/python2.6/threading.py', mode 'U' at 0x7fb708573db0>, '/usr/lib/python2.6/threading.py', ('.py', 'U', 1))
注意:使用 imp 模块时,你不能像这样做 imp.find_module('sqlalchmy.orm')
。