Tämä ohje on kopio kurssin Ohjelmistotekniikka Poetry-ohjeesta ohjeesta muutamin lisäyksin

Laajoissa ja monimutkaisissa ohjelmistoprojekteissa kaiken koodin tuottaminen itse ei ole enää käytännöllistä. Ei ole esimerkiksi järkevää, että jokaisessa ohjelmistoprojektissa toteutetaan oma ohjelmointirajapinta tietokantaoperaatioille, tai sovelluskehys koodin testaamiseen. Jotta pyörää ei tarvitsisi aina keksiä uudelleen, ovat ohjelmistokehittäjät kehittäneet valtavan määrän avoimen lähdekoodin kirjastoja, joita jokainen voi hyödyntää projekteissaan.

Kirjastojen lähdekoodi on usein luettavissa versionhallinta-alustoilla, kuten GitHubissa. Usein kirjastoja päivitetään jatkuvasti ja nämä päivitykset synnyttävät kirjastoista uusia versioita. Kirjastojen versioita julkaistaan erilaisiin rekistereihin, joista ne ovat helposti asennettavissa. The Python Package Index (PyPI) on eräs tämän kaltainen, Python-kirjastoille tarkoitettu rekisteri.

Projektissa käytettävät kirjastojen versiot ovat projektin riippuvuuksia. Riippuvuuksia asennetaan Python-projekteissa tyypillisesti projektikohtaisiin virtuaaliympäristöihin, jottei samalla tietokoneella olevien projektien riippuvuuksissa syntyisi ristiriitoja. Jotta riippuvuuksien hallinta virtuaaliympäristöissä sujuisi helposti, käytämme kurssilla Poetry-komentorivityökalua.

Huomioita komennoista

Monilla tietokoneilla Python-version kolme komennot suoritetaan python3-komennolla komennon python sijaan. Tarkista käytössä oleva versio komennolla:

python3 --version

Jos komentoa python3 ei jostain syystä löydy, tarkista python-komennon käyttämä versio komennolla:

python --version

Jos molemmissa tapauksissa versio on alle 3.12, asenna tietokoneellesi uusin Python-versio. Muista varmistaa asennuksen jälkeen, että oikea versio on käytössä. Muussa tapauksessa käytä komentoa, jonka käyttämä versio on vähintään 3.12.

Kurssilla käytetään Poetryn versiota 2.2.1. Jos koneellasi on vanhempi versio, se on syytä päivittää!

Asennus

Jos olet Dockerin käyttäjä, ei Poetryä ole välttämätöntä asentaa koneelle ollenkaan, katso täältä lisää!

Ennen kuin pääsemme tutustumaan Poetryn käyttöön tarkemmin, tulee se ensin asentaa. Seuraa alla olevista ohjeista tietokoneesi käyttöjärjestelmälle sopivaa asennusohjetta, kannattaa toki vilkaista myös Poetryn virallinen asennusohje.

HUOM: kaikki asennustavat saattavat vaatia terminaali-ikkunan sulkemisen ja uudelleen avaamisen, jotta Poetryn komennot alkavat toimia. Joissain tapauksissa on vaadittu jopa tietokoneen uudelleenkäynnistys.

Linux- ja macOS-asennus

Asenna Poetry suorittamalla terminaalissa seuraava komento:

curl -sSL https://install.python-poetry.org | POETRY_HOME=$HOME/.local python3 -

HUOM: jos python3-komentoa ei löydy, käytä sen sijaan komennon lopussa python-komentoa. Varmista kuitenkin, että Python-versio on oikea edellisen ohjeen mukaisesti.

HUOM: jos törmäät macOS-tietokoneella virheeseen SSL: CERTIFICATE_VERIFY_FAILED, avaa Python-asennuksen hakemisto komenolla open /Applications/Python\ 3.12 (korvaa “3.12” käytössä olevalla Python-versiolla) ja klikkaa hakemistossa olevaa tiedostoa Install Certificates.command. Odota, että operaatio valmistuu ja suorita tämän jälkeen edellä mainittu asennus-komento uudestaan.

Asennuksen jälkeen Poetry-binäärin polku tulee asettaa PATH-muuttujaan. Tämä onnistuu lisäämällä kotihakemiston .bashrc-tiedoston loppuun seuraava rivi:

export PATH="$HOME/.local/bin:$PATH"

Lisääminen onnistuu esimerkiksi muokkaamalla tiedostoa nano-editorin avulla, tai suorittamalla seuraava komento:

echo "export PATH=\"\$HOME/.local/bin:\$PATH\"" >> $HOME/.bashrc

HUOM: jos käytössäsi on zsh-komentorivi, on oikea konfiguraatiotiedosto .bashrc-tiedoston sijaan .zshrc-tiedosto. Voit tarkistaa käytössä olevan komentirivin komennolla echo $SHELL. Käytä tässä tapauksessa edellisessä komennossa käytetyn $HOME/.bashrc-polun sijaan polkua $HOME/.zshrc.

HUOM: jos käytössäsi on macOS-käyttöjärjestelmä ja bash-komentorivi, käytä edellisessä komennossa käytetyn $HOME/.bashrc-polun sijaan polkua $HOME/.bash_profile.

HUOM: käytä melkki-palvelimella edellisessä komennossa käytetyn $HOME/.bashrc-polun sijaan polkua $HOME/.profile.

Käynnistä terminaali uudestaan ja varmista, että asennus onnistui suorittamalla komento poetry --version. Komennon pitäisi tulostaa asennettu versio.

Windows-asennus

Asenna Poetry suorittamalla terminaalissa seuraava komento:

(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -

Asennuksen jälkeen Poetry-binäärin polku tulee asettaa PATH-muuttujaan. Lisää tämän ohjeen mukaisesti PATH-muuttujaan polku %APPDATA%\Python\Scripts.

Käynnistä terminaali uudestaan ja varmista, että asennus onnistui suorittamalla komento poetry --version. Komennon pitäisi tulostaa asennettu versio.

Ongelmia Poetryn asennuksessa?

Tämän sivun lopussa on ohjeita muutamiin ongelmatilanteisiin.

Asetusten hienosäätö

Ennen kuin aloitamme Poetryn käytön, tehdään pieni muutos konfiguraatioihin.

Näemme käytössä olevat konfiguraatiot komennolla poetry config --list, jonka tulostus näyttää seuraavalta

cache-dir = "/Users/mluukkai/Library/Caches/pypoetry"
experimental.system-git-client = false
installer.max-workers = null
installer.modern-installation = true
installer.no-binary = null
installer.parallel = true
virtualenvs.create = true
virtualenvs.in-project = false
virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.no-setuptools = false
virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}/virtualenvs"  # /Users/mluukkai/Library/Caches/pypoetry/virtualenvs
virtualenvs.prefer-active-python = false
virtualenvs.prompt = "{project_name}-py{python_version}"

Konfiguraatioissa on pari meitä kiinnostava kohtaa. cache-dir ja virtualenvs.path kertovat yhdessä, että jokaisen projektin virtuaaliympäristo, eli talletetaan oletusarvoisesti kansion /Users/mluukkai/Library/Caches/pypoetry alle. Tämä voi olla ok ratkaisu, mutta ainakin omaan makuun parempi on jos kunkin projektin virtuaaliympäristö talletetaan projektin hakemistoon. Tämä on yleinen käytäntö esimerkiksi JavaScript-ekosysteemissä. Konfiguraatio tapahtuu seuraavasti

poetry config virtualenvs.in-project true

Komennon poetry config --list tulostuksessa pitäisi nyt olla seuraava rivi:

virtualenvs.in-project = true

Projektin alustaminen

Harjoitellaan Poetryn käyttöä tekemällä pieni esimerkkiprojekti. Luo hakemisto poetry-testi haluamaasi hakemistoon. Hakemiston ei tarvitse löytyä Labtooliin rekisteröimästäsi repositoriosta. Avaa hakemisto terminaalissa ja suorita siellä komento:

poetry init --python "^3.12"

Komennon yhteydessä annettu --python "^3.12"-asetus asettaa projektin Python-version vaatimukseksi vähintään version 3.12. Komennon suorittaminen alkaa kysymään kysymyksiä. Voit vastata kysymyksiin haluamallasi tavalla ja kaikkien kohtien vastauksia voi myös muokata myöhemmin. Tämän vuoksi kysymysten ohittaminen Enter-painiketta painamalla on täysin hyvä vaihtoehto.

Kun viimeiseen kysymykseen on vastattu, katso hakemiston sisältöä. Hakemistoon pitäisi ilmestyä pyproject.toml-tiedosto, jonka sisältö on kutakuinkin seuraava:

[project]
name = "temp"
version = "0.1.0"
description = ""
authors = [
    {name = "Matti Luukkainen",email = "mluukkai@iki.fi"}
]
readme = "README.md"
requires-python = "^3.12"
dependencies = [
]

[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

Tiedoston [tool.poetry]-osio sisältää projektiin liittyviä yleistietoja, kuten sen nimen, kuvauksen ja ylläpitäjät. Osion alapuolella on osioita, jotka listaavat projektin riippuvuuksia. Osiossa [tool.poetry.dependencies] näemme poetry init-komennon suorituksen yhteydessä asettamamme Python-version vaatimuksen, joka on muotoa python = "^3.12". ^3.12-merkintä tarkoittaa, että projektin käyttö vaatii vähintään Python-version 3.12.

Tehdään pari pientä muutosta tiedostoon. Ensinnäkin maininta readme-tiedostosta pitää poistaa, sillä sellaista ei projektissa ole. Lisätään tiedostoon myös seuraava:

[tool.poetry]
package-mode = false

Lisäystä ei voi tehdä mihin tahansa kohtaan, sopiva paikka lisäykselle on esim. ennen määrittelyä [build-system].

Syy lisäykselle on selitetty dokumentaatiossa.

Kun pyproject.toml-tiedosto on tullut tutuksi ja yllämainitut muutokset on tehty, viimeistellään projektin alustaminen suorittamalla komento:

poetry install

Komennon suorittaminen tekee projektille vaadittavat alustustoimenpiteet, kuten virtuaaliympäristön alustamisen ja riippuvuuksien asentamisen. Tämän vuoksi komento tulee suorittaa aina ennen kuin uutta projektia aletaan käyttämään.

Virtuaaliympäristön alustamisen lisäksi tämä komento asentaa ainoastaan projektin riippuvuudet, ei projektia itseään.

Komennon suorittamisen poetry install jälkeen hakemistoon pitäisi ilmestyä tiedosto poetry.lock. Tiedosto sisältää kaikkien asennettujen riippuvuuksien versiotiedot. Sen tietojen avulla Poetry pystyy aina asentamaan poetry install -komennolla riippuvuuksista täsmälleen oikeat versiot. Tästä syystä tiedosto tulee lisätä versionhallintaan.

Tekemiemme asetusten muutosten takia hakemistoon tulee myös tiedosto .venv johon Poetry tallentaa projektin virtuaaliympäristön riippuvuuksineen. Tätä tiedostoa ei tule tallentaa versionhallintaan, eli se on syytä lisätä heti tiedostoon .gitignore.

Kannattaa huomata, että hakemistoa .venv ei oletusarvoisesti näe komennolla ls, sillä Unix-tyyppisissä käyttöjärjestelmissä pisteellä alkavat ovat piilotiedostoja. Komento ls -a tuo näkyviin myös piilotiedostot/hakemistot. Vielä parempi muoto voi olla, ls -la, joka tulostaa tiedot hieman laajemmassa muodossa:

Riippuvuuksien asentaminen

Varoitus: pip

Olet saattanut asentaa Pythonin tarvitsemia riippuvuuksia pip-komennolla. Älä käytä pipiä tällä kurssilla sillä jos teet niin, teet 99.9% todennäköisyydellä jotain väärin.

Tällä kurssilla riippuvuudet asennetaan poetryllä.

Asennetaan seuraavaksi projektiimme ensimmäisen riippuvuus. Riippuvuuksien löytäminen onnistuu helpoiten Googlettamalla ja etsimällä hakutuloksista sopivia GitHub-repositorioita, tai PyPI-sivuja. Asennetaan esimerkkinä projektiimme cowsay-kirjasto. Tämä onnistu projektin juurihakemistossa (samassa hakemistossa, missä pyproject.toml-tiedosto sijaitsee) komennolla:

poetry add cowsay

Asennuksen komento on siis muotoa poetry add <kirjasto>. Komennon suorittamisen jälkeen huomaamme, että pyproject.toml-tiedoston [tool.poetry.dependencies]-osion alla on uutta sisältöä:

[tool.poetry.dependencies]
python = "^3.12"
cowsay = "^2.0.3"

poetry add-komento asentaa oletusarvoisesti kirjaston uusimman version, joka oli komennon suoritushetkellä 2.0.3. Usein tämä on juuri se, mitä haluamme tehdä. Voimme kuitenkin asentaa halutessamme esimerkiksi cowsay-kirjaston version 1.0 komennolla:

poetry add cowsay==1.0

Jos haluaisimme poistaa kirjaston projektimme riippuvuuksien joukosta, se onnistuisi komennolla:

poetry remove cowsay

Pidetään kuitenkin cowsay-kirjasto toistaiseksi asennettuna.

Komentojen suorittaminen virtuaaliympäristössä

Lisätään seuraavaksi poetry-testi-hakemistoon hakemisto src ja sinne tiedosto index.py. Lisätään tiedostoon seuraavat koodirivit:

import cowsay

cowsay.tux("Poetry is awesome!")

Koodissa käytämme import-lausetta saadaksemme cowsay-kirjaston käyttöömme. Jos suoritamme tiedoston terminaalissa komennolla:

python3 src/index.py

On lopputuloksena seuraava virheilmoitus:

ModuleNotFoundError: No module named 'cowsay'

Tämä johtuu siitä, että emme ole projektin virtuaaliympäristön sisällä, jonka vuoksi Python ei löydä projektimme riippuvuuksia. Asia korjaantuu käyttämällä run komentoa:

poetry run python3 src/index.py

poetry run-komento siis suorittaa annetun komennon virtuaaliympäristössä, jonka sisällä Python löytää riippuvuutemme.

Kun projektia kehitetään aktiivisesti ja komentoja suoritetaan terminaalissa jatkuvasti, on kätevintä olla koko ajan virtuaaliympäristön sisällä. Voimme siirtyä virtuaaliympäristön sisään komennolla shell:

poetry shell

Kun olemme virtuaaliympäristössä, komentorivin syöterivin edessä on suluissa virtuaaliympäristön nimi:

$ (poetry-testi-IhtScY6W-py3.12)

Virtuaaliympäristön sisällä voimme suorittaa komennon “normaalisti”, eli ilman run-komentoa:

python3 src/index.py

Voimme lähteä virtuaaliympäristöstä komennolla exit.

Poetryn tuodut riippuvuudet ovat vain virtuaalisessa ympäristössä saatavilla, VS Coden sisäänrakennettu “debugging mode” (F5 oletuksena) ei välttämättä toimi. Koita ensin eval $(poetry env activate) ja vasta sen jälkeen käynnistä VS Code code /path/to/projekt komennolla.

Kehityksaikaiset riippuvuudet

Poetryn avulla riippuvuuksia on mahdollista ryhmitellä niiden käyttötarkoituksen mukaan. Melko yleinen tapa ryhmitellä riippuvuuksia on ryhmitellä ne kehityksen ja suorituksen aikaisiksi riippuvuuksiksi. Kehitysaikaisia riippuvuuksia tarvitaan ohjelmiston kehityksen aikana, mutta ne eivät ole välttämättömiä ohjelman suorituksessa.

Komennon poetry add suorittaminen asentaa oletusarvoisesti riippuvuudet [tool.poetry.dependencies]-osion alle. Näiden riippuvuuksien lisäksi voimme asentaa projektiimme riippuvuuksia, joita tarvitsemme vain kehityksen aikana. Näitä riippuvuuksia ovat kaikki ne, joita itse sovelluksen käynnistäminen (esimerkiksi python3 src/index.py-komennon suorittaminen) ei tarvitse.

Kehityksenaikaisten riippuvuuksien asentaminen onnistuu antamalla poetry add-komennolle --group dev-flagi. Esimerkiksi pian tutuksi tulevan pytest-kirjaston voi asentaa kehityksaikaiseksi riippuvuudeksi seuraavalla komennolla:

poetry add pytest --group dev

Komennon suorittaminen lisää pytest-kirjaston riippuvuudeksi [tool.poetry.group.dev.dependencies]-osion alle:

[tool.poetry.group.dev.dependencies]
pytest = "^7.4.2"

Kehityksenaikaisten riippuvuuksien määritteleminen on kätevää, koska se vähentää asennettavien riippuvuuksien määrää tapauksessa, jossa haluamme vain suorittaa sovelluksen. Tässä tilanteessa riippuvuuksien asentamisen voi tehdä komennolla poetry install --without dev.

Varoitus: pip

Olet saattanut asentaa Pythonin tarvitsemia riippuvuuksia pip-komennolla. Älä käytä pipiä tällä kurssilla sillä jos teet niin, teet 99.9% todennäköisyydellä jotain väärin.

Tällä kurssilla riippuvuudet asennetaan poetryllä.

Ratkaisuja yleisiin ongelmiin

Punainen valitus komennon poetry install suorituksessa

Kymmenet kurssin opiskelijat ovat törmänneet seuraavaan ongelmaan suorittaessaan komentoa poetry install:

Kuten valitus sanoo, syitä on kaksi. Ensimmäinen näistä johtuu siitä, että projektissa ei ole readme-tiedostoa. Vika on helppo korjata poistamalla määrittely tiedostosta pyproject.toml

Toisen ongelman syy kerrotaan dokumentaatiossa. Ongelmasta pääsee eroon lisäämällä tiedostoon pyproject.toml

[tool.poetry]
package-mode = false

Huomaa, että et voi lisätä tätä mihin tahansa kohtaan. Sopiva paikka on esim. loppuun, juuri ennen [build-system] määrittelyä:

[tool.poetry]
package-mode = false

[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

Virtuaaliympäristö ei ole päällä

Yrität suorittaa testejä, ja käy seuraavasti:

$ pytest src/tests
pytest: command not found

Syynä on se, että komento toimii ainoastaan kun virtuaaliympäristö on aktivoituna, eli antaa komento

eval $(poetry env activate)

Nyt komento (todennäköisesti) toimii:

pytest src/tests

Sama tilanne ohjelmaa suoritettaessa voi antaa hieman erinäköisen virheilmoituksen:

$ python src/index.py
Traceback (most recent call last):
  File "/Users/mluukkai/opetus/ohtu25/cow/index.py", line 1, in <module>
    import cowsay
ModuleNotFoundError: No module named 'cowsay'

Syynä jälleen se, että ei olla virtuaaliympäristössä. Voi olla, että komento aiheuttaa saman virheen vaikka virtuaaliympäristö on jo käynnistetty. Tämä johtuu siitä, että kirjastoa ei ole vielä asennettu. Eli tulee varmistaa, että kirjasto on mainittu tiedostossa pyproject.toml ja että komento poetry install on suoritettu.

Jos tästä huolimatta tulee valitus siitä, että ohjelman käyttämä kirjasto ei löydy (ja kirjasto on varmuudella asennettu), asenna riippuvuudet ja virtuaaliympäristö uudelleen, eli anna komennot:

rm -rf .venv
rm poetry.lock
poetry install

Yritä tämän jälkeen uudelleen!

Poetry ei löydä oikeaa pythonia

Jos törmäät seuraavaan virheilmoitukseen

Python 2.7 will no longer be supported in the next feature release of Poetry (1.2).
You should consider updating your Python version to a supported one.

Note that you will still be able to manage Python 2.7 projects by using the env command.
See https://python-poetry.org/docs/managing-environments/ for more information.

The currently activated Python version 2.7.16 is not supported by the project (^3.12).
Trying to find and use a compatible version.

eräs tapa korjata tilanne Macilla ja ehkä myös Linuxilla on editoida tiedoston ~/.poetry.bin/poetry ensimmäisellä rivillä mainittu Pythonin polku. Oletusarvoinen polku on todennäköisesti seuraava

#!/usr/bin/python

Polku tulee Macilla muuttaa (todennäköisesti) muotoon

#!/usr/local/bin/python3

Oikea polku kannattaa varmistaa komennolla which python3.

Keyring-ongelma

Jos poetry install-komennon suorittaminen pyytää keyring-salasanaa, ongelma pitäisi ratketa suorittamalla terminaalissa export PYTHON_KEYRING_BACKEND=keyring.backends.fail.Keyring ja sen jälkeen suorittamalla komento poetry install uudestaan. Kyseisen rivin voi laittaa .bashrc (tai vastaavaan) tiedostoon, jotta sitä ei tarvitse suorittaa jokaisen terminaali-istunnon aluksi.

urllib3 or chardet doesn’t match a supported

Joissain tilanteissa Poetry hajoaa kokonaan ja jokainen komento aiheuttaa seuraavan virheen:

/usr/lib/python3/dist-packages/requests/init.py:89: RequestsDependencyWarning: urllib3 (1.26.12) or chardet (3.0.4) doesn't match a supported version!
warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported "

Ongelma korjaantuu komennolla

pip install requests --upgrade

Muita ongelmia

Usein Poetry-ongelmat ratkeavat seuraavilla toimenpiteillä:

  1. Varmista, että Poetrystä on asennettu uusin versio suorittamalla komento poetry self update
  2. Varmista, että pyproject.toml-tiedostossa on oikea Python version vaatimus:

    [tool.poetry.dependencies]
    python = "^3.12"
    

    Jos versio on väärä, muuta se oikeaksi ja suorita komento poetry update

  3. Tyhjennä välimuisti suorittamalla komennot poetry cache clear pypi --all ja poetry cache clear PyPi --all

  4. Listaa projektissa käytössä olevat virtuaaliympäristöt komennolla poetry env list ja poista ne kaikki yksitellen komennolla poetry env remove <nimi>. Esimerkiksi seuraavasti:

    $ poetry env list
    unicafe-jLeQYxxf-py3.12 (Activated)
    $ poetry env remove unicafe-jLeQYxxf-py3.12
    Deleted virtualenv: /Users/kalleilv/Library/Caches/pypoetry/virtualenvs/unicafe-jLeQYxxf-py3.12
    

    Kun virtuaaliympäristöt on poistettu, suorita komento poetry install

Kun kaikki toimenpiteet on suoritettu, yritä suorittaa epäonnistunut Poetry-komento uudestaan.