Gestione delle dipendenze Python quale strumento scegliere?
Python dependency management which tool to choose?
Un confronto approfondito tra Poetry, Pip e Conda

Pubblicato originariamente su https://mathdatasimplified.com il 13 giugno 2023.
Motivazione
Alla crescita del progetto di data science, aumentano anche il numero di dipendenze. Per mantenere l’ambiente del progetto riproducibile e mantenibile, è importante utilizzare uno strumento efficiente di gestione delle dipendenze.
Quindi, ho deciso di confrontare tre strumenti popolari per la gestione delle dipendenze: Pip, Conda e Poetry. Dopo una valutazione attenta, sono convinto che Poetry superi gli altri due opzioni in termini di efficienza e prestazioni.
In questo articolo, esamineremo i vantaggi di Poetry e evidenzieremo le sue principali differenze rispetto a Pip e Conda.
- Plugin Notable Il Plugin ChatGPT Che Automatizza L’Analisi Dei Dati.
- Dati non strutturati diventano strutturati con LLMs
- Smetti di Codificare Duramente in un Progetto di Data Science – Usa invece File di Configurazione
Pacchetti disponibili
Avere una vasta selezione di pacchetti semplifica la ricerca del pacchetto e della versione specifica che meglio si adatta alle proprie esigenze.
Conda
Alcuni pacchetti, come “snscrape”, non possono essere installati con Conda. Inoltre, alcune versioni, come Pandas 2.0, potrebbero non essere disponibili per l’installazione tramite Conda.
Anche se è possibile utilizzare pip all’interno di un ambiente virtuale Conda per affrontare le limitazioni dei pacchetti, Conda non può tenere traccia delle dipendenze installate con pip, rendendo difficile la gestione delle dipendenze.
$ conda list# pacchetti nell'ambiente presso /Users/khuyentran/miniconda3/envs/test-conda:## Nome Versione Build Channel$ conda list # pacchetti nell'ambiente presso /Users/khuyentran/miniconda3/envs/test-conda: # # Nome Versione Build Channel
Pip
Pip può installare qualsiasi pacchetto dal Python Package Index (PyPI) e da altri repository.
Poetry
Poetry consente anche l’installazione di pacchetti dal Python Package Index (PyPI) e da altri repository.
Numero di dipendenze
Ridurre il numero di dipendenze in un ambiente semplifica il processo di sviluppo.
Conda
Conda fornisce un isolamento completo dell’ambiente, gestendo sia i pacchetti Python che le dipendenze a livello di sistema. Ciò può comportare dimensioni di pacchetto più grandi rispetto ad altri gestori di pacchetti, consumando potenzialmente più spazio di archiviazione durante l’installazione e la distribuzione.
$ conda install pandas$ conda list # pacchetti nell'ambiente presso /Users/khuyentran/miniconda3/envs/test-conda:## Nome Versione Build Channel blas 1.0 openblas bottleneck 1.3.5 py311ha0d4635_0 bzip2 1.0.8 h620ffc9_4 ca-certificates 2023.05.30 hca03da5_0 libcxx 14.0.6 h848a8c0_0 libffi 3.4.4 hca03da5_0 libgfortran 5.0.0 11_3_0_hca03da5_28 libgfortran5 11.3.0 h009349e_28 libopenblas 0.3.21 h269037a_0 llvm-openmp 14.0.6 hc6e5704_0 ncurses 6.4 h313beb8_0 numexpr 2.8.4 py311h6dc990b_1 numpy 1.24.3 py311hb57d4eb_0 numpy-base 1.24.3 py311h1d85a46_0 openssl 3.0.8 h1a28f6b_0 pandas 1.5.3 py311h6956b77_0 pip 23.0.1 py311hca03da5_0 python 3.11.3 hb885b13_1 python-dateutil 2.8.2 pyhd3eb1b0_0 pytz 2022.7 py311hca03da5_0 readline 8.2 h1a28f6b_0 setuptools 67.8.0 py311hca03da5_0 six 1.16.0 pyhd3eb1b0_1 sqlite 3.41.2 h80987f9_0 tk 8.6.12 hb8d0fd4_0 tzdata 2023c h04d1e81_0 wheel 0.38.4 py311hca03da5_0 xz 5.4.2 h80987f9_0 zlib 1.2.13 h5a0b063_0
Pip
Pip installa solo le dipendenze richieste da un pacchetto.
$ pip install pandas$ pip listPackage Version--------------- -------numpy 1.24.3pandas 2.0.2pip 22.3.1python-dateutil 2.8.2pytz 2023.3setuptools 65.5.0six 1.16.0tzdata 2023.3
Poetry
Poetry installa anche solo le dipendenze richieste da un pacchetto.
$ poetry add pandas$ poetry shownumpy 1.24.3 Pacchetto fondamentale per il calcolo degli array in Pythonpandas 2.0.2 Potenti strutture dati per l'analisi dei dati, il tempo...python-dateutil 2.8.2 Estensioni al modulo datetime standard di Pythonpytz 2023.3 Definizioni dei fusi orari mondiali, moderni e storici six 1.16.0 Utilità di compatibilità Python 2 e 3tzdata 2023.3 Fornitore di dati sui fusi orari IANA
Disinstalla pacchetti
La disinstallazione dei pacchetti e delle loro dipendenze libera spazio su disco, previene l’accumulo di spazzatura superflua e ottimizza l’utilizzo delle risorse di archiviazione.
Pip
Pip rimuove solo il pacchetto specificato, non le sue dipendenze, il che può portare all’accumulo di dipendenze inutilizzate nel tempo. Ciò può comportare un aumento dell’utilizzo dello spazio di archiviazione e potenziali conflitti.
$ pip install pandas$ pip uninstall pandas$ pip listPackage Version--------------- -------numpy 1.24.3pip 22.0.4python-dateutil 2.8.2pytz 2023.3setuptools 56.0.0six 1.16.0tzdata 2023.3
Conda
Conda rimuove il pacchetto e le sue dipendenze.
$ conda install -c conda pandas$ conda uninstall -c conda pandasRaccolta metadati del pacchetto (repodata.json): fattoRisoluzione dell'ambiente: fatto## Piano pacchetti ## localizzazione dell'ambiente: /Users/khuyentran/miniconda3/envs/test-conda specifiche rimosse: - pandasI seguenti pacchetti saranno RIMOSSI: blas-1.0-openblas bottleneck-1.3.5-py311ha0d4635_0 libcxx-14.0.6-h848a8c0_0 libgfortran-5.0.0-11_3_0_hca03da5_28 libgfortran5-11.3.0-h009349e_28 libopenblas-0.3.21-h269037a_0 llvm-openmp-14.0.6-hc6e5704_0 numexpr-2.8.4-py311h6dc990b_1 numpy-1.24.3-py311hb57d4eb_0 numpy-base-1.24.3-py311h1d85a46_0 pandas-1.5.3-py311h6956b77_0 python-dateutil-2.8.2-pyhd3eb1b0_0 pytz-2022.7-py311hca03da5_0 six-1.16.0-pyhd3eb1b0_1Procedere ([sì]/no)? Preparazione della transazione: fattoVerifica della transazione: fattoEsecuzione della transazione: fattoPoetry
Poetry
Poetry rimuove anche il pacchetto e le sue dipendenze.
$ poetry add pandas$ poetry remove pandas • Rimozione di numpy (1.24.3) • Rimozione di pandas (2.0.2) • Rimozione di python-dateutil (2.8.2) • Rimozione di pytz (2023.3) • Rimozione di six (1.16.0) • Rimozione di tzdata (2023.3)
File di dipendenza
I file di dipendenza garantiscono la riproducibilità dell’ambiente del progetto software specificando le versioni esatte o gli intervalli di versioni dei pacchetti richiesti.
Ciò aiuta a ricreare lo stesso ambiente su diversi sistemi o in momenti diversi, garantendo la collaborazione tra sviluppatori con lo stesso set di dipendenze.
Conda
Per salvare le dipendenze in un ambiente Conda, è necessario scriverle manualmente in un file. Le versioni specificate in un file environment.yml possono comportare l’installazione di versioni diverse, introducendo potenzialmente problemi di compatibilità durante la riproduzione dell’ambiente.
Supponiamo di aver installato pandas versione 1.5.3 come esempio. Ecco un file environment.yml che specifica le dipendenze:
# environment.ymlname: test-condachannels: - defaultsdependencies: - python=3.8 - pandas>=1.5
Se un nuovo utente cerca di riprodurre l’ambiente quando l’ultima versione di pandas è 2.0, verrà invece installato pandas 2.0.
# Crea e attiva un ambiente virtuale$ conda env create -n env$ conda activate env# Elenco dei pacchetti nell'ambiente corrente$ conda list...pandas 2.0
Se il codice dipende dalla sintassi o dal comportamento specifico di pandas versione 1.5.3 e la sintassi è cambiata nella versione 2.0, l’esecuzione del codice con pandas 2.0 potrebbe introdurre bug.
Pip
Lo stesso problema può verificarsi con pip.
# requirements.txt pandas>=1.5
# Crea e attiva un ambiente virtuale$ python3 -m venv venv$ source venv/bin/activate# Installa le dipendenze$ pip install -r requirements.txt# Elenco dei pacchetti$ pip listPackage Version---------- -------pandas 2.0...
Puoi fissare la versione bloccandola in un file requirements.txt:
$ pip freeze > requirements.txt
# requirements.txtnumpy==1.24.3pandas==1.5.3python-dateutil==2.8.2pytz==2023.3six==1.16.0
Tuttavia, questo rende l’ambiente di codice meno flessibile e potenzialmente più difficile da mantenere nel lungo periodo. Qualsiasi modifica alle dipendenze richiederebbe modifiche manuali al file requirements.txt, il che può essere lungo e soggetto a errori.
Poetry
Poetry aggiorna automaticamente il file pyproject.toml durante l’installazione di un pacchetto.
Nell’esempio seguente, il pacchetto “pandas” viene aggiunto con il vincolo di versione ^1.5
. Questo approccio di versioning flessibile garantisce che il tuo progetto possa adattarsi alle nuove versioni senza aggiustamenti manuali.
$ poetry add 'pandas=^1.5'
# pyproject.toml[tool.poetry.dependencies]python = "^3.8"pandas = "^1.5"
Il file poetry.lock memorizza i numeri di versione precisi per ogni pacchetto e le sue dipendenze.
# poetry.lock...[[package]]name = "pandas"version = "1.5.3"description = "Powerful data structures for data analysis, time series, and statistics"category = "main"optional = falsepython-versions = ">=3.8"[package.dependencies]numpy = [ {version = ">=1.20.3", markers = "python_version < \"3.10\""}, {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, {version = ">=1.23.2", markers = "python_version >= \"3.11\""},]python-dateutil = ">=2.8.2"pytz = ">=2020.1"tzdata = ">=2022.1"...
Ciò garantisce coerenza nei pacchetti installati, anche se un pacchetto ha un intervallo di versioni specificato nel file pyproject.toml. Qui, possiamo vedere che pandas 1.5.3 è installato invece di pandas 2.0
$ poetry install$ poetry show pandasname : pandas version : 1.5.3 description : Powerful data structures for data analysis, time series, and statistics dependencies - numpy >=1.20.3 - numpy >=1.21.0 - numpy >=1.23.2 - python-dateutil >=2.8.1 - pytz >=2020.1
Separare le dipendenze per dev e prod
Separando le dipendenze, puoi distinguere chiaramente tra i pacchetti richiesti per scopi di sviluppo, come i framework di testing e gli strumenti di qualità del codice, dai pacchetti necessari per l’ambiente di produzione, che includono tipicamente le dipendenze principali.
Conda
Conda non supporta intrinsecamente dipendenze separate per diversi ambienti, ma un workaround prevede la creazione di due file di ambiente: uno per l’ambiente di sviluppo e uno per la produzione. Il file di sviluppo contiene sia le dipendenze di produzione che quelle di sviluppo.
# environment.ymlname: test-condachannels: - defaultsdependencies: # Pacchetti di produzione - numpy - pandas
# environment-dev.ymlname: test-conda-devchannels: - defaultsdependencies: # Pacchetti di produzione - numpy - pandas # Pacchetti di sviluppo - pytest - pre-commit
Pip
Anche Pip non supporta direttamente dipendenze separate, ma si può utilizzare un approccio simile con file di requisiti separati.
# requirements.txtnumpy pandas
# requirements-dev.txt-r requirements.txtpytestpre-commit
# Installa solo i pacchetti di produzione$ pip install -r requirements.txt# Installa sia i pacchetti di sviluppo che di produzione$ pip install -r requirements-dev.txt
Poetry
Poetry semplifica la gestione delle dipendenze supportando gruppi all’interno di un unico file. Ciò ti consente di tenere traccia di tutte le dipendenze in un unico luogo.
$ poetry add numpy pandas$ poetry add --group dev pytest pre-commit
# pyproject.toml[tool.poetry.dependencies]python = "^3.8"pandas = "^2.0"numpy = "^1.24.3"[tool.poetry.group.dev.dependencies]pytest = "^7.3.2"pre-commit = "^3.3.2"
Per installare solo le dipendenze di produzione:
$ poetry install --only main
Per installare sia le dipendenze di sviluppo che di produzione:
$ poetry install
Aggiorna un Ambiente
L’aggiornamento delle dipendenze è essenziale per beneficiare di correzioni di bug, miglioramenti delle prestazioni e nuove funzionalità introdotte nelle nuove versioni dei pacchetti.
Conda
Conda consente di aggiornare solo un pacchetto specificato.
$ conda install -c conda pandas$ conda install -c anaconda scikit-learn
# Nuove versioni disponibili$ conda update pandas$ conda update scikit-learn
In seguito, è necessario aggiornare manualmente il file environment.yaml per mantenerlo sincronizzato con le dipendenze aggiornate.
$ conda env export > environment.yml
Pip
Anche Pip consente di aggiornare solo un pacchetto specificato e richiede di aggiornare manualmente il file requirements.txt.
$ pip install -U pandas
$ pip freeze > requirements.txt
Poetry
Utilizzando Poetry, puoi usare il comando update
per aggiornare tutti i pacchetti specificati nel file pyproject.toml. Questa azione aggiorna automaticamente il file poetry.lock, garantendo la coerenza tra le specifiche dei pacchetti e il file di blocco.
$ poetry add pandas scikit-learn# Nuove versioni disponibilipoetry updateAggiornamento dipendenzeRisoluzione dipendenze... (0.3s)Scrittura file di bloccoOperazioni sui pacchetti: 0 installazioni, 2 aggiornamenti, 0 rimozioni • Aggiornamento pandas (2.0.0 -> 2.0.2) • Aggiornamento scikit-learn (1.2.0 -> 1.2.2)
Risoluzione delle Dipendenze
I conflitti di dipendenza si verificano quando i pacchetti o le librerie necessari per un progetto hanno versioni in conflitto o dipendenze incompatibili. La corretta risoluzione dei conflitti è fondamentale per evitare errori, problemi di esecuzione o fallimenti del progetto.
Pip
Pip installa i pacchetti in modo sequenziale, il che significa che installa ciascun pacchetto uno alla volta, seguendo l’ordine specificato. Questo approccio sequenziale può talvolta portare a conflitti quando i pacchetti hanno dipendenze incompatibili o requisiti di versione.
Ad esempio, supponiamo di installare pandas==2.0.2
per primo, che richiede numpy>=1.20.3
. Successivamente, si installa numpy==1.20.2
utilizzando pip. Anche se questo creerà conflitti di dipendenza, pip procederà con l’aggiornamento della versione di numpy.
$ pip install pandas==2.0.2$ pip install numpy==1.22.2Collecting numpy=1.20.2 Attempting uninstall: numpy Found existing installation: numpy 1.24.3 Uninstalling numpy-1.24.3: Successfully uninstalled numpy-1.24.3ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.pandas 2.0.2 requires numpy>=1.20.3; python_version < "3.10", but you have numpy 1.20.2 which is incompatible.Successfully installed numpy-1.20.2
Conda
Conda utilizza un risolutore SAT per esplorare tutte le combinazioni di versioni di pacchetti e dipendenze al fine di trovare un insieme compatibile.
Ad esempio, se un pacchetto esistente ha una specifica restrizione per le sue dipendenze (ad es. statsmodels==0.13.2 richiede numpy>=1.21.2,<2.0a0), e il pacchetto che si desidera installare non soddisfa tale requisito (ad es. numpy<1.21.2), conda non solleverà immediatamente un errore. Invece, cercherà diligentemente le versioni compatibili di tutti i pacchetti richiesti e delle loro dipendenze, segnalando un errore solo se non viene trovata una soluzione adeguata.
$ conda install 'statsmodels==0.13.2'$ conda search 'statsmodels==0.13.2' --infodependencies: - numpy >=1.21.2,<2.0a0 - packaging >=21.3 - pandas >=1.0 - patsy >=0.5.2 - python >=3.9,<3.10.0a0 - scipy >=1.3$ conda install 'numpy<1.21.2'...Package ca-certificates conflicts for:python=3.8 -> openssl[version='>=1.1.1t,<1.1.2a'] -> ca-certificatesopenssl -> ca-certificatesca-certificatescryptography -> openssl[version='>1.1.0,<3.1.0'] -> ca-certificatesPackage idna conflicts for:requests -> urllib3[version='>=1.21.1,<1.27'] -> idna[version='>=2.0.0']requests -> idna[version='>=2.5,<3|>=2.5,<4']idnapooch -> requests -> idna[version='>=2.5,<3|>=2.5,<4']urllib3 -> idna[version='>=2.0.0']Package numexpr conflicts for:statsmodels==0.13.2 -> pandas[version='>=1.0'] -> numexpr[version='>=2.7.0|>=2.7.1|>=2.7.3']numexprpandas==1.5.3 -> numexpr[version='>=2.7.3']Package patsy conflicts for:statsmodels==0.13.2 -> patsy[version='>=0.5.2']patsyPackage chardet conflicts for:requests -> chardet[version='>=3.0.2,<4|>=3.0.2,<5']pooch -> requests -> chardet[version='>=3.0.2,<4|>=3.0.2,<5']Package python-dateutil conflicts for:statsmodels==0.13.2 -> pandas[version='>=1.0'] -> python-dateutil[version='>=2.7.3|>=2.8.1']python-dateutilpandas==1.5.3 -> python-dateutil[version='>=2.8.1']Package setuptools conflicts for:numexpr -> setuptoolspip -> setuptoolswheel -> setuptoolssetuptoolspython=3.8 -> pip -> setuptoolspandas==1.5.3 -> numexpr[version='>=2.7.3'] -> setuptoolsPackage brotlipy conflicts for:urllib3 -> brotlipy[version='>=0.6.0']brotlipyrequests -> urllib3[version='>=1.21.1,<1.27'] -> brotlipy[version='>=0.6.0']Package pytz conflicts for:pytzpandas==1.5.3 -> pytz[version='>=2020.1']statsmodels==0.13.2 -> pandas[version='>=1.0'] -> pytz[version='>=2017.3|>=2020.1']
Sebbene questo approccio migliori le possibilità di trovare una soluzione, può essere computazionalmente intensivo, soprattutto quando si tratta di ambienti estesi.
Poesia
Focalizzandosi sulle dipendenze dirette del progetto, il risolutore deterministico di Poetry riduce lo spazio di ricerca, rendendo il processo di risoluzione più efficiente. Valuta i vincoli specificati, come intervalli di versioni o versioni specifiche, e identifica immediatamente eventuali conflitti.
$ poetry add 'seaborn==0.12.2'$ poetry add 'matplotlib<3.1' Poiché poetry shell dipende da seaborn (0.12.2) che dipende da matplotlib (>=3.1,<3.6.1 || >3.6.1), è richiesto matplotlib.Quindi, poiché poetry shell dipende da matplotlib (<3.1), la risoluzione della versione ha fallito.
Questo feedback immediato aiuta a prevenire potenziali problemi dall’escalation e consente ai developer di affrontare il problema presto nel processo di sviluppo. Ad esempio, nel seguente codice, possiamo rilassare i requisiti per seaborn per consentire l’installazione di una versione specifica di matplotlib:
poetry add 'seaborn<=0.12.2' 'matplotlib<3.1' Operazioni del pacchetto: 1 installazione, 2 aggiornamenti, 4 rimozioni • Rimozione contourpy (1.0.7) • Rimozione fonttools (4.40.0) • Rimozione packaging (23.1) • Rimozione pillow (9.5.0) • Aggiornamento matplotlib (3.7.1 -> 3.0.3) • Installazione scipy (1.9.3) • Aggiornamento seaborn (0.12.2 -> 0.11.2)
Conclusione
In sintesi, Poetry offre diversi vantaggi rispetto a pip e conda:
- Selezione Ampia di Pacchetti: Poetry fornisce accesso a una vasta gamma di pacchetti disponibili su PyPI, consentendo di sfruttare un ecosistema diversificato per il proprio progetto.
- Gestione Efficienti delle Dipendenze: Poetry installa solo le dipendenze necessarie per un pacchetto specificato, riducendo il numero di pacchetti estranei nel proprio ambiente.
- Rimozione Semplificata dei Pacchetti: Poetry semplifica la rimozione dei pacchetti e delle loro dipendenze associate, rendendo facile mantenere un ambiente di progetto pulito ed efficiente.
- Risoluzione delle Dipendenze: Il risolutore deterministico di Poetry risolve efficientemente le dipendenze, identificando e affrontando prontamente eventuali incongruenze o conflitti.
Sebbene Poetry possa richiedere del tempo e degli sforzi aggiuntivi per imparare e adattarsi, l’utilizzo di un tool come Poetry può risparmiare tempo e sforzi a lungo termine.
Amo scrivere su concetti di data science e giocare con diversi strumenti di data science. È possibile rimanere aggiornati con i miei ultimi post:
- Iscrivendosi alla mia newsletter su Data Science Semplificata.
- Connettendosi con me su LinkedIn e Twitter.