python-3.x - Python3(pip):查找哪个包提供了特定的模块
问题描述
不要混淆,关于安装包、如何导入生成的模块以及列出哪些包可用的问题有很多。但是,如果您没有 requirements.txt 或 pipenv,似乎没有等效于 pip 的“--what-provides”选项。这个问题与上一个问题类似,但要求提供父包,而不是附加元数据。也就是说,这些其他问题并没有得到很多关注或许多公认的答案 - 例如。如何找到给定模块的 python 包元数据信息。于是奋勇向前……
例如,有两个包(仅举几例)将安装一个名为“serial”的模块 - 即“pyserial”和“serial”。因此,假设安装了其中一个包,我们可以使用 pip list 找到它:
python3 -m pip list | grep serial
但是,如果包的名称与模块的名称不匹配,或者您只是想找出要安装的包,在旧服务器或开发机器上工作,就会出现问题。
您可以检查导入模块的路径 - 这可以为您提供线索。但是继续这个例子......
>>> import serial
>>> print(serial.__file__)
/usr/lib/python3.6/site-packages/serial/__init__.py
它位于“串行”目录中,但实际上只安装了 pyserial,而不是串行:
> python3 -m pip list | grep serial
pyserial 3.4
我最接近的方法是通过“pipreqs ./”生成一个 requirements.txt,它可能会在依赖的子文件上失败(就像我一样),或者通过 pipenv 反向检查依赖关系(这会带来一整套新问题一起完成所有设置):
> pipenv graph --reverse
cymysql==0.9.15
ftptool==0.7.1
netifaces==0.10.9
pip==20.2.2
PyQt5-sip==12.8.1
- PyQt5==5.15.0 [requires: PyQt5-sip>=12.8,<13]
setuptools==50.3.0
wheel==0.35.1
有谁知道我错过了一个简单的解决方案来查找 pip 包提供特定模块的命令?
解决方案
我相信类似以下的东西应该有效:
#!/usr/bin/env python3
import importlib.util
import pathlib
import importlib_metadata
def get_distribution(file_name):
result = None
for distribution in importlib_metadata.distributions():
try:
relative = (
pathlib.Path(file_name)
.relative_to(distribution.locate_file(''))
)
except ValueError:
pass
else:
if distribution.files and relative in distribution.files:
result = distribution
break
return result
def alpha():
file_name = importlib.util.find_spec('serial').origin
distribution = get_distribution(file_name)
print("alpha", distribution.metadata['Name'])
def bravo():
import serial
file_name = serial.__file__
distribution = get_distribution(file_name)
print("bravo", distribution.metadata['Name'])
if __name__ == '__main__':
alpha()
bravo()
这只是一个代码示例,展示了如何获取特定模块所属的已安装项目的元数据。
重要的是get_distribution
函数,它以文件名作为参数。它可以是模块或包数据的文件名。如果该文件名属于安装在环境中的项目(pip install
例如通过),importlib.metadata.Distribution
则返回该对象。
更新(2021 年 2 月):
packages_distributions()
由于以下新添加的功能,看起来这可能会变得更容易importlib_metadata
:
推荐阅读
- http - 如何在 Go 中使用 httptrace 跟踪 http.Client
- python - 带有条件的列的 Python Pandas 计算
- python - Python到exe但保留图标
- apache-spark - 一张本地表和一张DB表的join操作背后的机制
- java - 无法在 Eclipse 中导入 Maven 项目,因为 Next 和 Finish 按钮被禁用
- java - 如何检查应用程序是否在较低的 Android 上具有 ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION 和其他存储权限
- android - 当我的焦点位于 Android TV 应用程序中的自定义键盘键上时,如何在 EditText 上显示静态光标
- javascript - 使用 Office.js API 获取电子邮件标头(原始)
- javascript - 多个元素的动态Javascript代码
- mongodb - 如何根据client.cer和CA_Intermediate.txt创建keystore,jks和trustore,jks连接MongoDB数据库