在运行时检查Python模块版本

时间:2009-04-02 16:53:08

标签: python module version

许多第三方Python模块都有一个属性,其中包含模块的版本信息(通常类似于module.VERSIONmodule.__version__),但有些则没有。

此类模块的特定示例是libxslt和libxml2。

我需要检查这些模块的正确版本是否在运行时使用。有没有办法做到这一点?

一个潜在的解决方案是在运行时读取源代码,对其进行哈希处理,然后将其与已知版本的哈希进行比较,但这很糟糕。

有更好的解决方案吗?

7 个答案:

答案 0 :(得分:225)

使用pkg_resources。从PyPI安装的任何东西至少应该有一个版本号。

>>> import pkg_resources
>>> pkg_resources.get_distribution("blogofile").version
'0.7.1'

答案 1 :(得分:6)

一些想法:

  1. 尝试检查所需版本中是否存在的功能。
  2. 如果没有功能差异,请检查函数参数和签名。
  3. 如果您无法从功能签名中找到它,请在导入时设置一些存根调用并检查其行为。

答案 2 :(得分:6)

我远离哈希。正在使用的libxslt版本可能包含某些类型的补丁,这些补丁不会影响您对它的使用。

作为替代方案,我建议你不要在运行时检查(不知道这是否是一个硬性要求)。对于我编写的具有外部依赖关系(第三方库)的python内容,我编写了一个脚本,用户可以运行该脚本来检查他们的python安装,看看是否安装了适当的模块版本。

对于没有定义'version'属性的模块,您可以检查它包含的接口(类和方法),看它们是否与他们期望的接口匹配。然后在您正在使用的实际代码中,假设第三方模块具有您期望的接口。

答案 3 :(得分:2)

您可以使用

pip freeze

以需求格式查看已安装的软件包。

答案 4 :(得分:0)

您可以为此使用importlib_metadata库。

如果您使用的是python <3.8,请先使用以下命令进行安装:

pip install importlib_metadata

自python 3.8起,它就包含在python的标准库中。

然后,要检查软件包的版本(在此示例中为lxml),请运行:

>>> from importlib_metadata import version
>>> version('lxml')
'4.3.1'

请记住,这仅适用于从PyPI安装的软件包。另外,您必须将软件包名称作为参数传递给version方法,而不是此软件包提供的模块名称(尽管它们通常是相同的)。

答案 5 :(得分:0)

我发现使用各种可用工具(包括this other answer中提到的最好的pkg_resources)非常不可靠,因为其中大多数工具无法涵盖所有​​情况。例如

  • 内置模块
  • 未安装的模块,只是添加到python路径(例如,通过您的IDE)
  • 可用同一模块的两个版本(在python路径中取代已安装的一个)

由于我们需要一种可靠的方法来获取 any 软件包,模块或子模块的版本,因此我最终写了getversion。使用起来非常简单:

from getversion import get_module_version
import foo
version, details = get_module_version(foo)

有关详细信息,请参见documentation

答案 6 :(得分:0)

对于不提供__version__的模块,以下操作很丑陋但可以起作用:

#!/usr/bin/env python3.6
import sys
import os
import subprocess
import re

sp = subprocess.run(["pip3", "show", "numpy"], stdout=subprocess.PIPE)
ver = sp.stdout.decode('utf-8').strip().split('\n')[1]
res = re.search('^Version:\ (.*)$', ver)
print(res.group(1))

#!/usr/bin/env python3.7
import sys
import os
import subprocess
import re

sp = subprocess.run(["pip3", "show", "numpy"], capture_output=True)
ver = sp.stdout.decode('utf-8').strip().split('\n')[1]
res = re.search('^Version:\ (.*)$', ver)
print(res.group(1))