Gri*_*cey 6 python python-3.x python-packaging
您可以使用以下命令获取 python 发行版的版本
import pkg_resources
pkg_resources.get_distribution("distro").version
Run Code Online (Sandbox Code Playgroud)
如果您知道发行版名称,那就太好了,但是我需要在运行时动态找出我的发行版名称。
# Common framework base app class, extended by each app
class App(object):
def get_app_version(self) -> str:
package_name = self.__class__.__module__.split('.')[0]
try:
return pkg_resources.get_distribution(package_name).version
except Exception:
return "development"
Run Code Online (Sandbox Code Playgroud)
这适用于应用程序包名称与分发名称相同的情况(例如requests
)。然而,一旦它们不匹配(例如my-app
包含 package my_app
),这就会失败。
所以我需要的是发行版和它们的包之间的映射,我确定它一定存在于某个地方,因为 pip 似乎知道在调用卸载时要删除什么:
$ pip uninstall requests
Uninstalling requests-2.21.0:
Would remove:
/home/user/.virtualenvs/app/lib/python3.6/site-packages/requests-2.21.0.dist-info/*
/home/user/.virtualenvs/app/lib/python3.6/site-packages/requests/*
Run Code Online (Sandbox Code Playgroud)
如何以编程方式访问此映射?
经过几个小时的探索pkg_resources
和阅读pip 卸载的源代码后,我得到了以下结果:
import inspect
import pkg_resources
import csv
class App(object):
def get_app_version(self) -> str:
# Iterate through all installed packages and try to find one that has the app's file in it
app_def_path = inspect.getfile(self.__class__)
for dist in pkg_resources.working_set:
try:
filenames = [
os.path.normpath(os.path.join(dist.location, r[0]))
for r in csv.reader(dist.get_metadata_lines("RECORD"))
]
if app_def_path in filenames:
return dist.version
except FileNotFoundError:
# Not pip installed or something
pass
return "development"
Run Code Online (Sandbox Code Playgroud)
这将迭代所有已安装的软件包,并且对于每个软件包,迭代其文件列表并尝试将其与当前文件进行匹配,这会将软件包与发行版进行匹配。这并不是很理想,我仍然愿意接受更好的答案。