如何找到Python中任何包的“导入名称”?
我想知道有没有一种可靠且一致的方法来获取一个Python包的“导入名称”或命名空间。举个例子:
包名; django-haystack
导入名称; haystack
或者
包名; ipython
导入名称; IPython
到目前为止,我知道PyPi并没有存储这些信息,我用PyPiXmlRpc检查过。
我还尝试自动下载这个包,解压它,然后查看.egg-info文件夹,但有些包根本没有这个文件夹。
任何帮助都将不胜感激,并且会用于一个很不错的小工具 :)
5 个回答
原则上,你需要获取这些信息的所有内容都在每个包里应该有的 setup.py
文件中。这个信息大致包括了包的名称、py_modules、ext_package 和 ext_modules,这些都是 Distribution 对象的一部分。实际上,这里有一个小脚本,它模拟了 distutils.core.setup
,专门用来获取这些信息。
import distutils.core
distutils.core._setup_stop_after = "config"
_real_setup = distutils.core.setup
def _fake_setup(*args, **kwargs):
global dist
dist = _real_setup(*args, **kwargs)
distutils.core.setup = _fake_setup
import sys
setup_file = sys.argv[1]
sys.argv[:] = sys.argv[1:]
import os.path
os.chdir(os.path.dirname(setup_file))
execfile(os.path.basename(setup_file))
cat = lambda *seq: sum((i for i in seq if i is not None), [])
pkgs = set(package.split('.')[0] for package
in cat(dist.packages,
dist.py_modules,
[m.name for m in cat(dist.ext_modules)],
[m.name for m in cat(dist.ext_package)]))
print "\n".join(pkgs)
对于很多包来说,这个方法效果很好,但以 numpy
为例,它就不行。因为 numpy 自己提供了 distutils,而且我没有找到明显的解决办法。
轮子
我知道这个问题已经有点老了,但wheel包现在已经被发明出来了!因为wheel其实就是一个压缩文件,解压后会放到lib/site-packages目录里,所以查看这个wheel文件的内容可以让你知道最上层的导入。
>>> import zipfile
>>> zf = zipfile.ZipFile('setuptools-35.0.2-py2.py3-none-any.whl')
>>> top_level = set([x.split('/')[0] for x in zf.namelist()])
>>> # filter out the .dist-info directory
>>> top_level = [x for x in top_level if not x.endswith('.dist-info')]
>>> top_level
['setuptools', 'pkg_resources', 'easy_install.py']
所以setuptools实际上给你提供了三个最上层的导入!
pip下载
现在pip有了一个下载命令,你只需运行 pip download setuptools
(或者你喜欢的任何包),然后就可以查看它的内容。
反向查找
从Python 3.10开始,有一个方便的功能可以进行反向查找(给定导入名称,找出对应的包)。官方的文档在这里
from importlib.metadata import packages_distributions
packages_distributions()
{'importlib_metadata': ['importlib-metadata'], 'yaml': ['PyYAML'], ...}
对于正向查找,你也可以简单地构建这个反向字典。
请注意,你这里所说的“包”其实不是包,而是一个叫做发行版的东西。一个发行版可以包含零个或多个模块或包。这意味着发行版和包之间并不是一一对应的关系。
我不太确定有没有办法在不安装发行版的情况下,知道它会安装哪些模块和包,除了实际安装它,然后查看文件系统的变化,看看新增了哪些包、模块和pth文件。