Kiểm tra phiên bản mô-đun Python trong thời gian chạy


118

Nhiều mô-đun Python của bên thứ ba có một thuộc tính chứa thông tin phiên bản cho mô-đun (thường là một cái gì đó giống như module.VERSIONhoặc module.__version__), tuy nhiên một số thì không.

Ví dụ cụ thể về các mô-đun như vậy là libxslt và libxml2.

Tôi cần kiểm tra xem phiên bản chính xác của các mô-đun này đang được sử dụng trong thời gian chạy. Có cách nào để làm việc này không?

Một giải pháp tiềm năng là đọc trong nguồn trong thời gian chạy, băm nó và sau đó so sánh nó với hàm băm của phiên bản đã biết, nhưng điều đó thật khó chịu.

Có giải pháp nào tốt hơn không?

Câu trả lời:


8

Tôi sẽ tránh xa băm. Phiên bản libxslt đang được sử dụng có thể chứa một số loại bản vá không ảnh hưởng đến việc bạn sử dụng nó.

Thay vào đó, tôi khuyên bạn không nên kiểm tra thời gian chạy (không biết đó có phải là một yêu cầu khó hay không). Đối với nội dung python tôi viết có phụ thuộc bên ngoài (thư viện bên thứ 3), tôi viết một tập lệnh mà người dùng có thể chạy để kiểm tra cài đặt python của họ để xem liệu các phiên bản mô-đun thích hợp đã được cài đặt hay chưa.

Đối với các mô-đun không có thuộc tính 'phiên bản' đã xác định, bạn có thể kiểm tra các giao diện mà nó chứa (các lớp và phương thức) và xem chúng có khớp với giao diện mà họ mong đợi hay không. Sau đó, trong mã thực tế mà bạn đang làm việc, giả sử rằng các mô-đun của bên thứ 3 có giao diện mà bạn mong đợi.


244

Sử dụng pkg_resources . Mọi thứ được cài đặt từ PyPI ít nhất phải có số phiên bản.

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

8
Cũng lưu ý rằng, tên gói phải là tên của mục nhập PyPI. Vì vậy, một cái gì đó như "pkg_resources.get_distribution ('MySQLdb'). Version" sẽ không hoạt động nhưng "pkg_resources.get_distribution ('mysql-python'). Version" sẽ.
Rahul

1
Nếu bạn đang chạy với tên tệp tuyệt đối, pkg_resourcescó thể chọn một phiên bản khác phủ bóng phiên bản bạn đang thực sự chạy vì nó có quyền ưu tiên cao hơn so với của bạn PYTHONPATHhoặc phiên bản tương tự.
tripleee

4
Trong trường hợp ai đó muốn biết làm thế nào để làm cho __version__thuộc tính: stackoverflow.com/q/17583443/562769
Martin Thoma

pkg_resourcesliên kết là một Lỗi 404
gerrit

Đối với quá trình xử lý tự động, hãy xem câu hỏi này
gerrit 22/11/19

6

Một vài ý tưởng:

  1. Hãy thử kiểm tra các chức năng tồn tại hoặc không tồn tại trong các phiên bản cần thiết của bạn.
  2. Nếu không có sự khác biệt về hàm, hãy kiểm tra các đối số và chữ ký của hàm.
  3. Nếu bạn không thể tìm ra điều đó từ các chữ ký hàm, hãy thiết lập một số lệnh gọi sơ khai tại thời điểm nhập và kiểm tra hành vi của chúng.

Các gói phải chỉ định phiên bản của chúng. Những ý tưởng này là hoàn toàn quá mức cần thiết đối với nhiệm vụ kiểm tra một phiên bản thường (ước tính là 99% trường hợp).
Zelphir Kaltstahl

2

Bạn có thể dùng

pip freeze

để xem các gói đã cài đặt ở định dạng yêu cầu.


1

Bạn có thể sử dụng importlib_metadatathư viện cho việc này.

Nếu bạn đang sử dụng python < 3.8, trước tiên hãy cài đặt nó bằng:

pip install importlib_metadata

Vì python 3.8nó được bao gồm trong thư viện tiêu chuẩn của python.

Sau đó, để kiểm tra phiên bản của gói (trong ví dụ này lxml), hãy chạy:

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

Hãy nhớ rằng điều này chỉ hoạt động đối với các gói được cài đặt từ PyPI. Ngoài ra, bạn phải chuyển tên gói làm đối số cho versionphương thức, thay vì tên mô-đun mà gói này cung cấp (mặc dù chúng thường giống nhau).


0

Tôi thấy không đáng tin cậy khi sử dụng các công cụ khác nhau có sẵn (bao gồm cả công cụ tốt nhất pkg_resourcesđược đề cập trong câu trả lời khác này ), vì hầu hết chúng không bao gồm tất cả các trường hợp. Ví dụ

  • mô-đun tích hợp
  • mô-đun chưa được cài đặt mà chỉ được thêm vào đường dẫn python (ví dụ: bằng IDE của bạn)
  • có sẵn hai phiên bản của cùng một mô-đun (một phiên bản trong đường dẫn python thay thế phiên bản đã cài đặt)

Vì chúng tôi cần một cách đáng tin cậy để lấy phiên bản của bất kỳ gói, mô-đun hoặc mô-đun con nào, nên tôi đã viết getversion . Nó khá đơn giản để sử dụng:

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

Xem tài liệu để biết chi tiết.


0

Đối với các mô-đun không cung cấp __version__những điều sau là xấu nhưng hoạt động:

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

hoặc là

#!/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))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.