Created on 18 Sep 2018 ;    Modified on 25 Sep 2018 ;    Translationenglish

Perché in una app django le voci install_requires del setup.py possono essere diverse da quelle di requirements.txt di pip

Questa nota mi è stata suggerita dalla lettura di questa interrogazione su stackoverflow: Reference requirements.txt for the install_requires kwarg in setuptools setup.py file?

Il contesto

Per capire il contesto, lo riassumo sinteticamente qui di seguito.

Quando si sviluppa una applicazione Python, ci si può porre il problema di condividerla con altri sviluppatori. A questo fine Python prevede un sistema di distribuzione standardizzato, tramite il modulo distutils, e degli stumenti più avanzati: i setuptools.

Senza entrare nel dettaglio [1], uno dei primi passi da fare, consiste nel compilare un file, setup.py, che descrive come è formato un modulo Python, eventualmente come compilarlo, e di quali librerie di supporto (ovvero: dipendenze) ha bisogno.

In setup.py le dipendenze si indicano con la sezione:

...
install_requires = ['lib1', 'lib2', ...],
...

Il software d'installazione di Python [2] elabora il file setup.py eseguendo i passi necessari all'installazione. Quando elabora la sezione install_requires, installa le librerie in essa elencate.

D'altro canto, di solito, abbiamo la necessità d'installare un intero ambiente applicativo. In questo caso lanceremo un comando del tipo:

pip install -r requirements.txt

Questo comando istruisce pip ad installare tutti i moduli elencati nel file requirements.txt.

La domanda

Nel contesto predetto, l'autore della domanda a stackoverflow si chiede:

"Per quale motivo devo duplicare l'elenco delle dipendenze, indicandolo sia in install_requires che in requirements.txt?"

La risposta

Le risposte in stackoverflow mettono in rilievo che le esigenze cui rispondono i due elenchi predetti sono diverse.

install_requires ha lo scopo di elencare le sole dipendenze necessarie alla installazione del singolo modulo.

Invece requirements.txt elenca tutti i moduli necessari alla installazione di un ambiente applicativo. E un ambiente del genere può richiedere l'installazione di decine di moduli, ognuno con le sue dipendenze. Quindi usualmente requirements.txt é un sovrainsieme di install_requires.

Se la duplicazione di voci nei due elenchi da' fastidio, si può pensare di elidere da requirements.txt le voci già presenti in install_requires, a patto che siano necessarie solo a quel modulo. O che siano correttamente riportate anche nei setup.py degli altri moduli che formano l'applicazione.

E Django che c'entra?

C'entra, e come se c'entra. Facciamo un attimo mente locale: una app Django usualmente è sviluppata in modo tale da essere riusabile in diversi progetti Django. Quindi ha un suo setup.py con la sezione install_requires.

D'altro canto, quando installo un progetto Django, userò una serie di app, tra cui la precedente. Quindi il file requirements.txt tipicamente elencherà l'installazione delle app in questione, non dei moduli da cui dipendono le app. A meno che il progetto non abbia delle dipendenze dirette anche da uno o più moduli utilizzati dalle app. In tal caso posso avere duplicazione della dichiarazione di una dipendenza.

Spesso la duplicazione della dichiarazione non è un problema. pip la gestisce verificando a priori se un modulo è già installato. In caso affermativo non lo ricarica. Eventualmente dichiarando la versione del modulo già caricato ed aggiornandola se è inferiore al livello richiesto. Quest'ultimo comportamento potrebbe crearci dei problemi, nel caso che app diverse dipendano dallo stesso modulo, ma con versioni diverse!


[1]Una introduzione, lavorando in Django, si può trovare qui: Advanced tutorial: How to write reusable apps; e in Python qui: Tutorial on Packaging and Distributing Projects.
[2]

Ne esiste più di uno. Noi qui consideriamo pip, con il comando:

pip install module_to_install