【问题标题】:Ensuring minimum version for imported Python package确保导入的 Python 包的最低版本
【发布时间】:2020-10-09 14:49:41
【问题描述】:

大多数 Python 包都遵循在 [package_name].version.version 处以字符串形式提供版本的约定。让我们以 Numpy 为例。假设我想导入 Numpy,但要确保最低版本是 1.18.1。这就是我目前所做的:

import numpy as np

if tuple(map(int, np.version.version.split('.'))) < (1, 18, 1):
    raise ImportError('Numpy version too low! Must be >= 1.18.1')

虽然这似乎可行,但它需要我先导入包,然后才能检查版本。如果条件不满足就不用导入包就好了。

这似乎也有点“hacky”,感觉可能有一种使用 Python 标准库的方法可以做到这一点。像version('numpy') &gt; '1.18.1' 这样的东西。但是一直没找到。

有没有办法在 Python 标准库的范围内导入包之前检查它的版本?

我正在寻找 Python 代码中的编程解决方案。告诉我使用 requirements.txtpip install 不是在回答问题。


编辑以添加上下文:将此包添加到我的requirements.txt 没有用,因为导入的包应该是可选的依赖项。此代码将进入一个子模块,该子模块通过try 语句可选地加载到__init__.py 中。本质上,该包的某些功能只有在找到并成功导入最低版本的包时才可用。

【问题讨论】:

  • 通常使用requirements.txt 文件或最近使用python-poetry 来管理项目中的版本来控制他们获得的软件包版本。不过,这并不能回答您关于如何在 python 代码中处理它的问题。
  • 就我而言,我关心的是可选依赖项。所以,我不能在requirements.txt 中列出包,但是如果存在可选依赖项,我的包中有子模块会被加载。
  • pip show packagepip list?我想有一个与您的问题相关的 SO Q&A。
  • 从我的帖子中很明显我正在寻找 Python 中的编程解决方案。
  • 也许这个问题的答案可能会有所帮助stackoverflow.com/questions/11887762/…

标签: python python-3.x versioning


【解决方案1】:

使用子进程为特定包运行pip show,然后解析结果以将安装的版本与您的要求进行比较。

>>> import subprocess
>>> result = subprocess.run(['pip', 'show', 'numpy'], stdout=subprocess.PIPE)
>>> result.stdout
b'Name: numpy\r\nVersion: 1.17.4\r\nSummary: NumPy is the fundamental package for array computing with Python.\r\nHome-page: https://www.numpy.org\r\nAuthor: Travis E. Oliphant et al.\r\nAuthor-email: None\r\nLicense: BSD\r\nLocation: c:\\python38\\lib\\site-packages\r\nRequires: \r\nRequired-by: scipy, scikit-learn, perfplot, pandas, opencv-python, matplotlib\r\n'

>>> result = subprocess.run(['pip', 'show', 'pandas'], stdout=subprocess.PIPE)
>>> for thing in result.stdout.splitlines():
...     print(thing)

    
b'Name: pandas'
b'Version: 0.25.3'
b'Summary: Powerful data structures for data analysis, time series, and statistics'
b'Home-page: http://pandas.pydata.org'
b'Author: None'
b'Author-email: None'
b'License: BSD'
b'Location: c:\\python38\\lib\\site-packages'
b'Requires: numpy, python-dateutil, pytz'
b'Required-by: '
>>>

>>> from email.header import Header
>>> result = subprocess.run(['pip', 'show', 'pandas'], stdout=subprocess.PIPE)
>>> h = Header(result.stdout)
>>> print(str(h))
Name: pandas
Version: 0.25.3
Summary: Powerful data structures for data analysis, time series, and statistics
Home-page: http://pandas.pydata.org
Author: None
Author-email: None
License: BSD
Location: c:\python38\lib\site-packages
Requires: python-dateutil, pytz, numpy
Required-by: 

>>> d = {}
>>> for line in result.stdout.decode().splitlines():
...     k,v = line.split(':',1)
...     d[k] = v
    
>>> d['Version']
' 0.25.3'
>>>

或者看看一切:

>>> result = subprocess.run(['pip', 'list'], stdout=subprocess.PIPE)
>>> for thing in result.stdout.splitlines():
    print(thing)

    
b'Package          Version   '
b'---------------- ----------'
b'-illow           6.2.1     '
b'aiohttp          3.6.2     '
b'appdirs          1.4.3     '
...

【讨论】:

    【解决方案2】:

    使用容器来控制程序的所有依赖项和运行时环境。一个简单的方法是创建一个 Docker 映像,其中包含您需要的确切版本的 python。然后使用requirements.txt 来安装您需要的正确版本的正确 python 模块。

    最后,您可以创建一个 shell 脚本或类似的东西,一键启动 docker 容器。

    或者(如果 Docker 看起来有点矫枉过正),请查看venv

    【讨论】:

    • 从我的帖子中可以明显看出我正在寻找 Python 中的编程解决方案。
    猜你喜欢
    • 1970-01-01
    • 2019-07-14
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    • 2018-02-27
    • 1970-01-01
    • 2021-04-28
    • 2021-01-17
    相关资源
    最近更新 更多