134

许多第三方 Python 模块都有一个保存模块版本信息的属性(通常类似于module.VERSIONor module.__version__),但有些没有。

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

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

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

有没有更好的解决方案?

4

7 回答 7

258

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

>>> import pkg_resources
>>> pkg_resources.get_distribution("blogofile").version
'0.7.1'
于 2011-02-08T22:54:17.217 回答
12

如果您使用的是 python >=3.8,则可以使用内置库中的模块。要检查包的版本(在此示例中lxml),请运行:

>>> from importlib.metadata import version
>>> version('lxml')
'4.3.1'

此功能也已移植到旧版本的 python ( <3.8) 中,但您需要先安装一个单独的库:

pip install importlib_metadata

然后检查一个包的版本(在这个例子中lxml)运行:

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

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

于 2019-02-25T15:37:07.457 回答
8

我会远离散列。正在使用的 libxslt 版本可能包含不影响您使用它的某种类型的补丁。

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

对于没有定义“版本”属性的模块,您可以检查它包含的接口(类和方法)并查看它们是否与预期的接口匹配。然后在您正在处理的实际代码中,假设第 3 方模块具有您期望的接口。

于 2009-04-02T17:02:16.617 回答
6

一些想法:

  1. 尝试检查所需版本中存在或不存在的功能。
  2. 如果没有函数差异,请检查函数参数和签名。
  3. 如果您无法从函数签名中弄清楚,请在导入时设置一些存根调用并检查它们的行为。
于 2009-04-02T16:58:33.053 回答
2

您可以使用

pip freeze

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

于 2016-09-23T03:18:03.333 回答
2

我发现使用各种可用的工具(包括这个其他答案pkg_resources提到的最好的工具)非常不可靠,因为它们中的大多数并不涵盖所有情况。例如

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

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

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

有关详细信息,请参阅文档

于 2019-07-06T00:43:48.310 回答
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))
于 2019-09-26T20:27:21.043 回答