在运行时检查Python模块版本

在运行时检查Python模块版本,python,module,version,Python,Module,Version,许多第三方Python模块都有一个属性,该属性保存模块的版本信息(通常类似于module.version或module 此类模块的具体示例是libxslt和libxml2 我需要检查运行时是否使用了这些模块的正确版本。有办法做到这一点吗 一个可能的解决方案是在运行时读入源代码,对其进行散列,然后将其与已知版本的散列进行比较,但这很糟糕 有更好的解决方案吗?一些想法: 尝试检查所需版本中存在或不存在的函数 如果没有函数差异,请检查函数参数和签名 如果您无法从函数签名中找到它,请在导入时设置一些存根

许多第三方Python模块都有一个属性,该属性保存模块的版本信息(通常类似于
module.version
module

此类模块的具体示例是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
    ),请运行:


    此功能已移植到较旧版本的python(
    我发现使用各种可用工具(包括所提到的最好的
    pkg_资源
    )是非常不可靠的,因为大多数工具并不涵盖所有情况

    • 内置模块
    • 模块没有安装,只是添加到python路径中(例如通过IDE)
    • 同一模块的两个版本可用(一个在python路径中,取代已安装的模块)
    因为我们需要一种可靠的方法来获取任何包、模块或子模块的版本,所以我最后写了一篇文章。使用起来非常简单:

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

    有关详细信息,请参阅。

    对于不提供
    \uuuuuu版本\uuuuuuuuu
    的模块,以下内容很难看,但可以正常工作:

    #!/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))
    


    还要注意的是,包名必须是PyPI条目的名称。因此类似于“pkg_resources.get_distribution('MySQLdb').version”的内容将不起作用,但“pkg_resources.get_distribution('mysql-python').version”会起作用will.如果您使用绝对文件名运行,
    pkg_resources
    可能会选择一个与您实际运行的版本不同的版本,因为它在您的
    PYTHONPATH
    或类似文件上具有更高的优先级。如果有人想知道如何制作
    pkg_version
    属性:
    pkg_resources
    链接i对于自动处理来说,这是一个错误,请参阅软件包应指定其版本。对于通常(估计99%的情况下)检查版本的简单任务来说,这些想法完全是多余的。
    >>> from importlib_metadata import version
    >>> version('lxml')
    '4.3.1'
    
    from getversion import get_module_version
    import foo
    version, details = get_module_version(foo)
    
    #!/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))