Ho un file requirements.txt
con un elenco di pacchetti necessari per il mio ambiente virtuale. È possibile scoprire se tutti i pacchetti menzionati nel file sono presenti. Se mancano alcuni pacchetti, come scoprire quali sono i pacchetti mancanti?Come verificare se il mio Python ha tutti i pacchetti richiesti?
risposta
Il divinatorio modo di farlo è tramite il pkg_resources
API. I requisiti sono scritti in un formato comprensibile da setuptools. Per esempio:
Werkzeug>=0.6.1
Flask
Django>=1.3
Il codice di esempio:
import pkg_resources
from pkg_resources import DistributionNotFound, VersionConflict
# dependencies can be any iterable with strings,
# e.g. file line-by-line iterator
dependencies = [
'Werkzeug>=0.6.1',
'Flask>=0.9',
]
# here, if a dependency is not met, a DistributionNotFound or VersionConflict
# exception is thrown.
pkg_resources.require(dependencies)
È possibile eseguire pip freeze
per vedere cosa è stato installato e confrontarlo con il file requirements.txt
.
Se si desidera installare i moduli mancanti è possibile eseguire pip install -r requirements.txt
e che installerà eventuali moduli mancanti e dire alla fine quali erano mancanti e installati.
Se requirements.txt è come:
django
oursql
sys
notexistingmodule
Poi il seguente script vi dirà che i moduli mancanti:
#!/usr/bin/python3
fname = 'requirements.txt'
with open(fname, 'r', encoding='utf-8') as fhd:
for line in fhd:
try:
exec("import " + line)
except:
print("[ERROR] Missing module:", line)
Ciò stampare:
[ERROR] Missing module: notexistingmodule
Questo fallirebbe se requisiti.txt contiene informazioni sulla versione, ad es. 'django == 1.5.1' –
Infatti. E fallirà se i moduli sono elencati anche in una riga. Funzionerà, come affermato, se requirement.txt elenca un modulo per riga. –
Sei sicuro che il nome del pacchetto sia uguale al nome del modulo? – warvariuc
È possibile creare una virtualenv con accesso ai pacchetti del sito del sistema e verificare verificare se il pacchetto (o un altro dipendenze) sono installati oppure no. In questo modo i pacchetti non sono realmente installati (se vuoi solo controllare). Un esempio utilizzando virtualenv wrapper sarebbe:
$ cat requirements.txt
requests
simplejson
$ mkvirtualenv --system-site-packages test
Running virtualenv with interpreter /usr/bin/python2
New python executable in test/bin/python2
Also creating executable in test/bin/python
Installing setuptools, pip...done.
$ pip install -r requirements.txt
Downloading/unpacking requests (from -r requirements.txt (line 1))
Downloading requests-2.10.0-py2.py3-none-any.whl (506kB): 506kB downloaded
Requirement already satisfied (use --upgrade to upgrade): simplejson in /usr/lib/python2.7/dist-packages (from -r requirements.txt (line 2))
Installing collected packages: requests
Successfully installed requests
Cleaning up...
$ pip install -r requirements.txt
Requirement already satisfied (use --upgrade to upgrade): requests in /home/yucer/.virtualenvs/test/lib/python2.7/site-packages (from -r requirements.txt (line 1))
Requirement already satisfied (use --upgrade to upgrade): simplejson in /usr/lib/python2.7/dist-packages (from -r requirements.txt (line 2))
Cleaning up...
$ deactivate
$ rmvirtualenv test
Removing test...
Sulla base del answer by Zaur, supponendo che si in effetti utilizza un file requirements.txt
, si può decidere un test di unità, forse in tests/test_requirements.py
, che conferma la disponibilità di pacchetti.
L'approccio generale è:
import pathlib
import unittest
import pip
import pkg_resources
class TestRequirements(unittest.TestCase):
def test_requirements(self): # pylint: disable=no-self-use
"""Recursively confirm that requirements are available.
This implementation is tested to be compatible with pip 9.0.1.
"""
requirements_path = pathlib.Path(__file__).parents[1]/'requirements.txt'
requirements = pip.req.parse_requirements(str(requirements_path), session=pip.download.PipSession())
requirements = [str(r.req) for r in requirements]
pkg_resources.require(requirements)
Si noti che questa risposta utilizza pathlib
che è disponibile in Python 3, ma non in Python 2. Se si utilizza Python 2, prima installare il backport per questo che è pathlib2
.
Questa è veramente una grande idea! –
Come bonus, questo rileva automaticamente in modo ricorsivo i requisiti di versione in conflitto - questi sarebbero insoddisfacenti. –