Çalışma zamanında bir Python modülü sürümünü kontrol etme


119

Birçok üçüncü taraf Python modülünün, modülün sürüm bilgilerini tutan bir özniteliği vardır (genellikle module.VERSIONveya benzeri bir şey module.__version__), ancak bazılarında yoktur.

Bu tür modüllerin özel örnekleri libxslt ve libxml2'dir.

Bu modüllerin doğru sürümünün çalışma zamanında kullanıldığını kontrol etmem gerekiyor. Bunu yapmanın bir yolu var mı?

Potansiyel bir çözüm, kaynakta çalışma zamanında okumak, hash'lemek ve ardından bilinen sürümün karması ile karşılaştırmak olabilir, ancak bu çok kötü.

Daha iyi çözümler var mı?

Yanıtlar:


8

Hashingden uzak dururdum. Kullanılan libxslt sürümü, onu kullanımınızı etkilemeyen bir tür yama içerebilir.

Alternatif olarak, çalışma zamanında kontrol etmemenizi öneririm (bunun zor bir gereklilik olup olmadığını bilmiyorum). Harici bağımlılıkları olan (3. parti kitaplıklar) yazdığım python materyalleri için, kullanıcıların uygun modül sürümlerinin kurulu olup olmadığını görmek için python kurulumlarını kontrol etmek için çalıştırabilecekleri bir betik yazıyorum.

Tanımlanmış bir 'sürüm' özniteliği olmayan modüller için içerdiği arabirimleri (sınıflar ve yöntemler) inceleyebilir ve bekledikleri arabirimle eşleşip eşleşmediklerini görebilirsiniz. Ardından, üzerinde çalıştığınız gerçek kodda, 3. taraf modüllerin beklediğiniz arayüze sahip olduğunu varsayın.


245

Pkg_resources kullanın . PyPI'den yüklenen herhangi bir şeyin en azından bir sürüm numarası olmalıdır.

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

8
Ayrıca, paket adının PyPI girişine ait olması gerektiğini unutmayın. Yani "pkg_resources.get_distribution ('MySQLdb'). Version" gibi bir şey çalışmayacak, ancak "pkg_resources.get_distribution ('mysql-python'). Version" çalışacaktır.
Rahul

1
Mutlak bir dosya adıyla pkg_resourcesçalıştırıyorsanız, sizin PYTHONPATHveya benzerine göre daha yüksek önceliğe sahip olduğu için gerçekte çalıştırdığınız sürümü gölgeleyen farklı bir sürüm alabilir .
üçlü

4
Birinin __version__özniteliğin nasıl yapılacağını bilmek istemesi durumunda : stackoverflow.com/q/17583443/562769
Martin Thoma

pkg_resourcesbağlantı Hata 404
gerrit

Otomatik işleme için bu soruya
gerrit

6

Bazı fikirler:

  1. Gerekli sürümlerinizde mevcut olan veya olmayan işlevleri kontrol etmeyi deneyin.
  2. İşlev farklılığı yoksa, işlev bağımsız değişkenlerini ve imzalarını inceleyin.
  3. İşlev imzalarından anlayamazsanız, içe aktarma zamanında bazı saplama çağrıları ayarlayın ve davranışlarını kontrol edin.

Paketler kendi versiyonlarını belirtmelidir. Bu fikirler, genellikle (vakaların tahmini% 99'u) bir sürümü kontrol etmenin kolay görevi için tamamen aşırıdır.
Zelphir Kaltstahl

2

Kullanabilirsiniz

pip freeze

kurulu paketleri gereksinimler formatında görmek için.


1

Bunun için importlib_metadatakitaplığı kullanabilirsiniz .

Python <kullanıyorsanız 3.8, önce şunu kurun:

pip install importlib_metadata

Python'dan beri python'un 3.8standart kütüphanesine dahil edilmiştir.

Ardından, bir paketin sürümünü (bu örnekte lxml) kontrol etmek için şunu çalıştırın:

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

Bunun yalnızca PyPI'den yüklenen paketler için çalıştığını unutmayın. Ayrıca, versionbu paketin sağladığı modül adı yerine (genellikle aynı olsalar da) , yönteme bağımsız değişken olarak bir paket adı iletmelisiniz .


0

Mevcut çeşitli araçları ( bu diğer cevaptapkg_resources bahsedilen en iyisi dahil) kullanmak oldukça güvenilmez buldum , çünkü bunların çoğu tüm durumları kapsamıyor. Örneğin

  • yerleşik modüller
  • modüller kurulu değil ancak python yoluna yeni eklendi (örneğin IDE'niz tarafından)
  • aynı modülün iki versiyonu mevcuttur (biri kurulu olanın yerine python yolunda)

Herhangi bir paketin, modülün veya alt modülün sürümünü almak için güvenilir bir yola ihtiyacımız olduğundan , getversion'ı yazdım . Kullanımı oldukça basittir:

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

Ayrıntılar için belgelere bakın.


0

__version__Aşağıdakileri sağlamayan modüller için çirkin ama işe yarıyor:

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

veya

#!/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))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.