从包中获取 Python 包分发版本 [英] Getting Python package distribution version from within a package

查看:51
本文介绍了从包中获取 Python 包分发版本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您可以使用

import pkg_resources
pkg_resources.get_distribution("distro").version

如果您知道发行版名称,那就太好了,但是我需要在运行时动态找出我的发行版名称.

This is great if you know the distribution name, however I need to dynamically figure out my distribution name at runtime.

# 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"

这适用于应用程序包名称与分发名称相同的情况(例如 requests).但是,一旦它们不匹配(例如 my-app 包含包 my_app),这就会失败.

This works for cases where the app's package name is the same as the distribution name (e.g. requests). However this fails once they don't match (e.g. my-app containing package my_app).

所以我需要的是发行版和它们的包之间的映射,我确定它一定存在于某个地方,因为 pip 似乎知道在您调用卸载时要删除的内容:

So what I need is a mapping between distributions and their packages, which I'm sure must exist somewhere since pip seems to know what to delete when you call uninstall:

$ 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/*

如何以编程方式访问此映射?

How do I programatically access this mapping?

推荐答案

我认为项目名称应该尽可能硬编码.如果没有,那么像下面这样的一些函数可以帮助找出包含当前文件(__file__)的已安装发行版的元数据:

I believe the project's name should be hard-coded if possible. If not then some function like the following could help figuring out the metadata for the installed distribution containing the current file (__file__):

import pathlib
import importlib_metadata

def get_project_distribution():
    for dist in importlib_metadata.distributions():
        try:
            relative = pathlib.Path(__file__).relative_to(dist.locate_file(''))
        except ValueError:
            pass
        else:
            if relative in dist.files:
                return dist
    return None

project_distribution = get_project_distribution()
if project_distribution:
    project_name = project_distribution.metadata['Name']
    version = project_distribution.metadata['Version']


更新(2021 年 2 月):


Update (February 2021):

由于 importlib_metadata 中新添加的 packages_distributions() 函数,看起来这会变得更容易:

Looks like this could become easier thanks to the newly added packages_distributions() function in importlib_metadata:

这篇关于从包中获取 Python 包分发版本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆