La fonction python ne renvoyant que la version du package dans un format lisible par machine:
from importlib.metadata import version
version('numpy')
Avant python 3.8:
pip install importlib-metadata
from importlib_metadata import version
version('numpy')
L'équivalent bash (ici également invoqué depuis python) serait beaucoup plus complexe (mais plus robuste - voir prudence ci-dessous):
import subprocess
def get_installed_ver(pkg_name):
bash_str="pip freeze | grep -w %s= | awk -F '==' {'print $2'} | tr -d '\n'" %(pkg_name)
return(subprocess.check_output(bash_str, shell=True).decode())
Exemple d'utilisation:
# pkg_name="xgboost"
# pkg_name="Flask"
# pkg_name="Flask-Caching"
pkg_name="scikit-learn"
print(get_installed_ver(pkg_name))
>>> 0.22
Notez que dans les deux cas, le pkg_name
paramètre doit contenir le nom du package au format renvoyé par pip freeze
et non tel qu'il est utilisé pendant import
, par exemple, scikit-learn
pas sklearn
ou Flask-Caching
pas flask_caching
.
Notez que bien que l'invocation pip freeze
dans la version bash puisse sembler inefficace, seule cette méthode s'avère suffisamment robuste pour empaqueter les particularités et les incohérences de nommage (par exemple, les soulignés vs les tirets, les petites vs les grandes majuscules et les abréviations telles que sklearn
vs scikit-learn
).
Attention: dans les environnements complexes, les deux variantes peuvent renvoyer des numéros de version surprenants, incompatibles avec ce que vous pouvez réellement obtenir pendant import
.
Un tel problème se pose lorsqu'il existe d'autres versions du package cachées dans un sous-dossier utilisateur site-packages
. Pour illustrer les dangers de l'utilisation, version()
voici une situation que j'ai rencontrée:
$ pip freeze | grep lightgbm
lightgbm==2.3.1
and
$ python -c "import lightgbm; print(lightgbm.__version__)"
2.3.1
vs.
$ python -c "from importlib_metadata import version; print(version(\"lightgbm\"))"
2.2.3
until you delete the subfolder with the old version (here 2.2.3) from the user folder (only one would normally be preserved by `pip` - the one installed as last with the `--user` switch):
$ ls /home/jovyan/.local/lib/python3.7/site-packages/lightgbm*
/home/jovyan/.local/lib/python3.7/site-packages/lightgbm-2.2.3.dist-info
/home/jovyan/.local/lib/python3.7/site-packages/lightgbm-2.3.1.dist-info
Un autre problème est d'avoir certains packages installés par conda dans le même environnement. S'ils partagent des dépendances avec vos packages installés par pip et que les versions de ces dépendances diffèrent, vous pouvez obtenir des rétrogradations de vos dépendances installées par pip.
Pour illustrer, la dernière version de numpy
disponible dans PyPI le 01-01-2020 était 1.18.0, tandis que dans le même temps la conda-forge
chaîne d'Anaconda n'avait que la version 1.17.3 numpy
comme dernière. Ainsi, lorsque vous avez installé un basemap
package avec conda (comme deuxième), votre ancien pip installé numpy
serait rétrogradé par conda à 1.17.3, et la version 1.18.0 deviendrait indisponible pour la import
fonction. Dans ce cas, ce version()
serait bien et pip freeze
/ ou conda list
mal:
$ python -c "from importlib_metadata import version; print(version(\"numpy\"))"
1.17.3
$ python -c "import numpy; print(numpy.__version__)"
1.17.3
$ pip freeze | grep numpy
numpy==1.18.0
$ conda list | grep numpy
numpy 1.18.0 pypi_0 pypi
show
commande dans pip: github.com/pypa/pip/issues/33