许多第三方 Python 模块都有一个属性,该属性包含模块的版本信息(通常类似于 module.VERSION或 module.__version__) ,但有些则没有。
module.VERSION
module.__version__
这类模块的特殊示例有 libxslt 和 libxml2。
我需要检查这些模块的正确版本是否在运行时使用。有办法吗?
一个可能的解决方案是在运行时读取源代码,散列它,然后将其与已知版本的散列进行比较,但这是令人讨厌的。
有更好的解决办法吗?
一些想法:
我会远离哈希。正在使用的 libxslt 版本可能包含某种类型的补丁,这种补丁不会影响您对它的使用。
作为替代方案,我建议您不要在运行时进行检查(不知道这是否是一个硬性要求)。对于我编写的具有外部依赖关系的 python 内容(第三方库) ,我编写了一个脚本,用户可以运行该脚本来检查他们的 python 安装是否安装了合适的模块版本。
对于那些没有定义“ version”属性的模块,您可以检查它包含的接口(类和方法) ,看它们是否与预期的接口匹配。然后在您正在编写的实际代码中,假设第三方模块具有您所期望的接口。
从 PyPI 安装的任何东西至少应该有一个版本号。
>>> import pkg_resources >>> pkg_resources.get_distribution("blogofile").version '0.7.1'
你可以用
pip freeze
以需求格式查看已安装的包。
如果您使用的是 python>=3.8,那么可以使用内置库中的模块来实现这一点。要检查包的版本(在本例中为 lxml) ,请运行:
>=3.8
lxml
>>> from importlib.metadata import version >>> version('lxml') '4.3.1'
这个功能已经被移植到旧版本的 python (<3.8)中,但是您需要首先安装一个单独的库:
<3.8
pip install importlib_metadata
然后检查包的版本(在这个例子中是 lxml)运行:
>>> from importlib_metadata import version >>> version('lxml') '4.3.1'
请记住,这只适用于从 PyPI 安装的包。另外,必须将包名作为参数传递给 version方法,而不是该包提供的模块名(尽管它们通常是相同的)。
version
我发现使用各种可用的工具(包括 另一个答案提到的最好的 pkg_resources)是相当不可靠的,因为它们中的大多数并不涵盖所有情况。比如说
pkg_resources
因为我们需要一种可靠的方法来获得 任何包、模块或子模块的版本,所以我最终编写了 获得版本。它的使用非常简单:
from getversion import get_module_version import foo version, details = get_module_version(foo)
有关详细信息,请参阅 文件。
对于不提供 __version__的模块,以下内容虽然难看,但是可以使用:
__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))