Cos'è poetry
Poetry è un tool per gestire le dipendenze e il packaging in Python.
Contrariamente a pip / requirements.txt, con poetry si possono dichiarare esclusivamente le dipendenze necessarie, poetry si occuperà di mantenere la lista delle versioni delle loro dipendenze.
Concettualmente si avvicina
a npm o yarn, infatti anche
poetry creerà un suo file .lock
.
Installazione Linux / OS X
curl -sSL https://install.python-poetry.org | python3 -
Installerà poetry nella seguente cartella $HOME/.local/bin
,
dovrete aggiungerla al vostro path.
Se usate bash basta aggiungete la seguente riga al .bashrc
:
export PATH=$PATH:$HOME/.local/bin
Aggiornamento
Se avete installato poetry con il suo installer basterà eseguire:
poetry self update
Configurazione
Per visualizzare le opzioni correnti basta eseguire:
poetry config --list
cache-dir = "/home/sherpya/.cache/pypoetry"
experimental.new-installer = true
installer.parallel = true
virtualenvs.create = true
virtualenvs.in-project = null
virtualenvs.path = "{cache-dir}/virtualenvs" # /home/sherpya/.cache/pypoetry/virtualenvs
L'unica opzione che consiglio di cambiare è virtualenvs.in-project
,
in questo caso poetry creerà il virtualenv nella cartella del progetto, con il
nome .venv
:
poetry config virtualenvs.in-project true
Ricordatevi di aggiungere /.venv
al
file .gitignore
Utilizzo
Vediamo adesso un esempio pratico: un progetto Django.
mkdir demo-django
cd demo-django
poetry init
Poetry ci farà qualche domanda, io ho cambiato solo la versione minima di Python in ^3.7
^3.7 significa che vanno bene tutte le major con 3 a partire dalla 3.7.
Package name [demo-django]:
Version [0.1.0]:
Description []:
Author [Gianluigi Tiesi <sherpya@netfarm.it>, n to skip]:
License []:
Compatible Python versions [^3.9]: ^3.7
Would you like to define your main dependencies interactively? (yes/no) [yes]
You can specify a package in the following forms:
- A single name (requests)
- A name and a constraint (requests@^2.23.0)
- A git url (git+https://github.com/python-poetry/poetry.git)
- A git url with a revision (git+https://github.com/python-poetry/poetry.git#develop)
- A file path (../my-package/my-package.whl)
- A directory (../my-package/)
- A url (https://example.com/packages/my-package-0.1.0.tar.gz)
Search for package to add (or leave blank to continue): django
Found 20 packages matching django
Enter package # to add, or the complete package name if it is not listed:
[0] Django
[1] django-503
[2] django-scribbler-django2.0
[3] django-filebrowser-django13
[4] django-tracking-analyzer-django2
[5] django-jchart-django3-uvm
[6] django-totalsum-admin-django3
[7] django-debug-toolbar-django13
[8] django-suit-redactor-django2
[9] django-django_csv_exports
> 0
Enter the version constraint to require (or leave blank to use the latest version): ^3.2.10
Ho specificato la versione di Django altrimenti avrebbe preso l'ultima disponibile 4.0, non compatibile con python 3.7 (sospetto sia un bug).
Per terminare l'aggiunta interattiva, premere invio alla domanda:
Add a package:
Qui possiamo aggiungere ad esempio iPython
Would you like to define your development dependencies interactively? (yes/no) [yes]
Search for package to add (or leave blank to continue): ipython
Found 20 packages matching ipython
Enter package # to add, or the complete package name if it is not listed:
[0] ipython
[1] twisted-ipython
[2] ipython-futhark
[3] ipython-cells
[4] ipython-odoo
[5] ipython2cwl
[6] progressbar-ipython
[7] ipython-ngql
[8] ipython-elasticsearch
[9] ipython-bg
> 0
Enter the version constraint to require (or leave blank to use the latest version):
Using version ^7.30.1 for ipython
Per terminare l'aggiunta interattiva, premere sempre invio alla domanda:
Add a package:
Ora poetry mostrerà un'anteprima del file che verrà generato:
[tool.poetry]
name = "demo-django"
version = "0.1.0"
description = ""
authors = ["Gianluigi Tiesi <sherpya@netfarm.it>"]
[tool.poetry.dependencies]
python = "^3.7"
Django = "^3.2.10"
[tool.poetry.dev-dependencies]
ipython = "^7.30.1"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Do you confirm generation? (yes/no) [yes]
A questo punto nella cartella troveremo il nostro file di configurazione del
progetto pyproject.toml
.
Per inizializzare il virtualenv e installare i pacchetti digitiamo il comando:
poetry install
Creating virtualenv demo in /tmp/demo/.venv
Installing dependencies from lock file
Package operations: 17 installs, 0 updates, 0 removals
• Installing parso (0.8.3)
• Installing ptyprocess (0.7.0)
• Installing traitlets (5.1.1)
• Installing wcwidth (0.2.5)
• Installing asgiref (3.4.1)
• Installing backcall (0.2.0)
• Installing decorator (5.1.0)
• Installing jedi (0.18.1)
• Installing matplotlib-inline (0.1.3)
• Installing pexpect (4.8.0)
• Installing pickleshare (0.7.5)
• Installing prompt-toolkit (3.0.24)
• Installing pygments (2.10.0)
• Installing pytz (2021.3)
• Installing sqlparse (0.4.2)
• Installing django (3.2.10)
• Installing ipython (7.30.1)
Per eseguire un comando utilizzando il venv possiamo utilizzare:
poetry run ./manage.py
Ricordate il ./
perché
altrimenti il comando non verrà trovato.
In alternativa è possibile attivare una shell simile al classico virtualenv:
poetry shell
Creiamo subito il nostro progetto Django anche se ovviamente possiamo aggiungere poetry ad un progetto esistente.
poetry shell
django-admin startproject demo .
Se volessimo aggiungere una dipendenza:
poetry add djangorestframework
# oppure
poetry add djangorestframework@^3.12.4
# o ancora
poetry add 'djangorestframework<4.0'
Using version ^3.12.4 for djangorestframework
Updating dependencies
Resolving dependencies... (0.1s)
Writing lock file
Package operations: 1 install, 0 updates, 0 removals
• Installing djangorestframework (3.12.4)
Nel nostro file di configurazione sarà aggiunta la dipendenza:
[tool.poetry.dependencies]
python = "^3.7"
Django = "^3.2.10"
djangorestframework = "^3.12.4"
Per rimuovere una dipendenza:
poetry remove djangorestframework
Updating dependencies
Resolving dependencies... (0.1s)
Writing lock file
Package operations: 0 installs, 0 updates, 1 removal
• Removing djangorestframework (3.12.4)
Il file poetry.lock
bisogna
versionarlo e committare ogni qual volta cambi per una modifica ad un pacchetto.
Per il deploy non occorre installare poetry sul server, possiamo farci generare
un requirements.txt
e
versionarlo, così da poterlo utilizzare con pip
.
poetry export --without-hashes > requirements.txt
il file generato:
asgiref==3.4.1; python_version >= "3.6"
django==3.2.10; python_version >= "3.6"
djangorestframework==3.12.4; python_version >= "3.5"
pytz==2021.3; python_version >= "3.6"
sqlparse==0.4.2; python_version >= "3.6"
typing-extensions==4.0.1; python_version < "3.8" and python_version >= "3.6"
Conversione di un progetto esistente (Django)
Per la conversione di un progetto esistente occorre analizzare sia il file settings.py
con
i pacchetti di cui abbiamo bisogno, sia il file requirements.txt
per
le versioni.
INSTALLED_APPS = [
'django.contrib.contenttypes',
'grappelli.dashboard',
'grappelli',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'oauth2_provider',
'corsheaders',
'rest_framework',
'django_filters',
'sequences.apps.SequencesConfig',
'tinymce',
...
]
I pacchetti da inserire nelle dipendenze sono i seguenti:
- django (ovviamente)
- grappelli
- oauth2_provider -> django-oauth-toolkit
- corsheaders -> django-cors-headers
- rest_framework -> djangorestframework
- django_filters -> django-filter
- sequences.apps.SequencesConfig -> django-sequences
- tinymce -> django-tinymce
ora guardiamo le versioni corrispondenti nel file requirements.txt
- Django@3.2.5
- django-grappelli@2.15.1
- django-oauth-toolkit@1.5.0
- django-cors-headers@3.7.0
- djangorestframework@3.12.4
- django-filter@2.4.0
- django-sequences@2.6
- django-tinymce@3.3.0
Procediamo con l'init e alla richiesta dei pacchetti inseriamoli come nella lista:
Search for package to add (or leave blank to continue): Django@3.2.5
Adding Django@3.2.5
Add a package: django-grappelli@2.15.1
Adding django-grappelli@2.15.1
Add a package: django-oauth-toolkit@1.5.0
Adding django-oauth-toolkit@1.5.0
Add a package: django-cors-headers@3.7.0
Adding django-cors-headers@3.7.0
Add a package: djangorestframework@3.12.4
Adding djangorestframework@3.12.4
Add a package: django-filter@2.4.0
Adding django-filter@2.4.0
Add a package: django-sequences@2.6
Adding django-sequences@2.6
Add a package: django-tinymce@3.3.0
Adding django-tinymce@3.3.0
Le dipendenze nel file pyproject.toml
:
[tool.poetry.dependencies]
python = "^3.7"
Django = "3.2.5"
django-grappelli = "2.15.1"
django-oauth-toolkit = "1.5.0"
django-cors-headers = "3.7.0"
djangorestframework = "3.12.4"
django-filter = "2.4.0"
django-sequences = "2.6"
django-tinymce = "3.3.0"
Ora
poetry install
Creating virtualenv django-demo in /tmp/django_demo/.venv
Updating dependencies
Resolving dependencies... (8.5s)
Writing lock file
Package operations: 24 installs, 0 updates, 0 removals
• Installing pycparser (2.21)
• Installing cffi (1.15.0)
• Installing wrapt (1.13.3)
• Installing asgiref (3.4.1)
• Installing certifi (2021.10.8)
• Installing charset-normalizer (2.0.9)
• Installing cryptography (36.0.0)
• Installing deprecated (1.2.13)
• Installing idna (3.3)
• Installing pytz (2021.3)
• Installing sqlparse (0.4.2)
• Installing urllib3 (1.26.7)
• Installing django (3.2.5)
• Installing jwcrypto (1.0)
• Installing oauthlib (3.1.1)
• Installing requests (2.26.0)
• Installing six (1.16.0)
• Installing django-cors-headers (3.7.0)
• Installing django-filter (2.4.0)
• Installing django-grappelli (2.15.1)
• Installing django-oauth-toolkit (1.5.0)
• Installing django-sequences (2.6)
• Installing django-tinymce (3.3.0)
• Installing djangorestframework (3.12.4)
dimenticavo...
poetry add psycopg2-binary
Using version ^2.9.2 for psycopg2-binary
Updating dependencies
Resolving dependencies... (3.6s)
Writing lock file
Package operations: 1 install, 0 updates, 0 removals
• Installing psycopg2-binary (2.9.2)
Possiamo ora provare se funziona lanciando la shell oppure:
poetry run ./manage.py
Possiamo generare il file requirements.txt
poetry export --without-hashes > requirements.txt
asgiref==3.4.1; python_version >= "3.6" and python_version < "4.0"
certifi==2021.10.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0"
cffi==1.15.0; python_version >= "3.6"
charset-normalizer==2.0.9; python_full_version >= "3.6.0" and python_version >= "3"
cryptography==36.0.0; python_version >= "3.6"
deprecated==1.2.13; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
django-cors-headers==3.7.0; python_version >= "3.6"
django-filter==2.4.0; python_version >= "3.5"
django-grappelli==2.15.1
django-oauth-toolkit==1.5.0
django-sequences==2.6; python_version >= "3.5" and python_version < "4.0"
django-tinymce==3.3.0
django==3.2.5; python_version >= "3.6"
djangorestframework==3.12.4; python_version >= "3.5"
idna==3.3; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.5"
jwcrypto==1.0
oauthlib==3.1.1; python_version >= "3.6"
psycopg2-binary==2.9.2; python_version >= "3.6"
pycparser==2.21; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
pytz==2021.3; python_version >= "3.6" and python_version < "4.0"
requests==2.26.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0"
six==1.16.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0"
sqlparse==0.4.2; python_version >= "3.6" and python_version < "4.0"
typing-extensions==4.0.1; python_version < "3.8" and python_version >= "3.6"
urllib3==1.26.7; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4"
wrapt==1.13.3; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
Aggiungiamo /.venv
al
file .gitignore
e
versioniamo pyproject.toml
, poetry.lock
e
il requirements.txt
generato.
Approfondimenti
Per ulteriori approfondimenti e la lista completa dei comandi, consiglio di consultare la documentazione ufficiale https://python-poetry.org/docs/
Gestire i pacchetti Python con Poetry