Kihagyás

Környezetkezelés

Mi az a Pixi?

A Python service függőségeinek és környezeteinek kezelésére a Pixi környezetkezelőt alkalmazzuk. Ez több forrásból merít (főleg Conda, uv és Poetry), és próbálja ezek pozitívumait megtartva a leguniverzálisabb Python csomagkezelést biztosítani. Több hasznos funkcióval bír, többek között

  • rendszerfüggetlen lock-fájlok támogatása és automatikus generálása
  • Conda csomagokkal való kompatibilitás
  • a Python csomagként való kezelése
  • több környezet definiálásának lehetősége

A Pixi használata lehetővé teszi, hogy egyszerűen – és az uv-nek köszönhetően rendkívül gyorsan – definiáljunk, telepítsünk és megosszunk környezeteket (akár különböző Python verziókkal, különböző operációs rendszereken), melyeket minimális manuális munkával, vagy akár automatikusan lehetséges a telepíteni a repo frissítésével.

Pixi és Conda

A Pixi és a Conda környezetkezelése néhol hasonlít, máshol eltér. A Pixi oldalán találunk egy összehasonlítást a kettőről. Ugyanakkor pár dolgot fontos kiemelni a témával kapcsolatban.

A talán legjelentősebb technikai különbség, hogy a Conda globális környezeteket hoz létre, melyeket bárhonnan aktiválhatunk. Ezzel szemben a Pixi lokálisan, az adott projekt mappájában állítja össze a környezeteket (ezeket meg is találjuk a <projekt mappa>/.pixi/envs könyvtárban). Így tehát a Pixi környezeteket nem érjük el automatikusan a projektmappán kívül.

Ennek hozománya, hogy a Pixi környezeteket nem is feltétlen szükséges aktiválni: a pixi run <parancs> a megadott parancsot automatikusan az adott projekt default környezetében futtatja (amennyiben persze a parancsot a projekt mappáján belül adjuk ki).

Fontos, hogy a Conda és a Pixi megél egymás mellett. Azaz nem kell letörölünk a Conda-t, vagy egyéb trükközést végeznünk, hogy használni tudjuk. Amennyiben a pixi run <parancs> parancsot adjuk ki, az a Pixi környezetet fogja használni, független attól, hogy van-e aktiválva Conda környezet.

Ugyanakkor ha csak simán a python <fájl> parancsot adjuk ki, akkor ezt a Pixi nem fogja automatikusan elkapni, így váratlan működés következhet (pl. a rendszerszintű Python interpreter futtat, vagy a Conda környezet, amennyiben aktiválva van). Ennek elkerülése érdekében a Pixi környezetet is tudjuk „aktiválni“ a pixi shell paranccsal. Ekkor bármilyen kiadott parancs a Pixi környezetnek megfelelően fut, továbbá a terminál sorainak elején megjelenik az aktivált környezet neve (Conda-hoz hasonlóan). A környezet deaktiválása az exit paranncsal történik.

Konfiguráció

A Pixi konfigurációja a pyproject.toml fájl tool.pixi táblájában található, itt definiáljuk a függőségeket, környezeteket és támogatott operációs rendszereket. A tool.pixi tábla felépítésének teljes leírásától eltekintenénk, ez megtalálható a Pixi dokumentációjában. Ennek ellenére az általa használt alapvető koncepciókat bemutatjuk.

A workspace tábla

Ez a projektre vonatkozó alapvető leírásokat tartalmaz, mint például a projekt neve, vagy a támogatott operációs rendszerek.

A feature.<feature_name> táblák

Ezek egy-egy aspektust, és az ehhez szükséges függőségeket definiálják. Alapvetően úgy gondolunk egy-egy „feature“-re, mint egyetlen dolog, amit a környezetünk tud (pl. futtatás, formázás, tesztelés).

Az environments.<env_name> táblák

Ezek egy-egy környezetet definiálnak. Pixi-ben egy környezet úgy áll elő, mint feature-ök összessége. Fontos, hogy alapértelmezésként minden környezet tartalmazza a default feature-t (vigyázat, nem a default környezetet). Amennyiben ezt el szeretnénk kerülni, úgy a no-default-feature flag-et be kell állítanunk. Emellett a környezetek esetén támogatott a solve-group paraméter, melynek funkciója, hogy az azonos solve-group-pal rendelkező környezetek azonos csomagverziókkal kerülnek rögzítésre, a rendszer közösen számolja függőségeik verzióit.

Ez utóbbinak segítségével érjük el, hogy a prod és a cicd környezetünk azonos csomagverziókat használjon annak ellenére, hogy a cicd környezet bővebb. Ezzel lehetővé tesszük, hogy a CI/CD job-ok során ugyanazok a problémák állhassanak elő, melyek élőben előjönnének.

A *.tasks táblák

Itt rögzíthetünk olyan „feladatokat“ (akár globálisan, akár feature specifikusan), amiket a pixi run paranccsal futtathatunk. Ezek gyakorlatilag előre definiált parancssoros hívások, esetlegesen definiált task-függőségekkel, melyeket szintén futtat a rendszer megfelelő sorrendben.

Függőségek és módosításuk

A futtatáshoz szükséges PyPI függőségeket a pyproject.toml fájl project táblájának dependencies listája tárolja. Új PyPI függőségeket a legegyszerűbben úgy adhatunk a futtatási környezethez, hogy ebbe a listába beszúrjuk. Ügyeljünk arra, hogy rögzítsük a csomag verzióját (==<verzió> segítségével), illetve az átláthatóság miatt lehetőleg tartsuk a betűrendet.

Miért nem a pixi táblába helyezzük a függőségeket?

Bár a Pixi-t tool.pixi tábla konfigurálja, a PEP 621 definiálja a project tábla szerkezetét, így azt a legtöbb modern csomagkezelő felhasználja, mint „kiindulási alap“. Ennek okán PyPI függőségeket itt definiálni általánosabb (emellett valamennyivel kényelmesebb és átláthatóbb is), mint a pixi saját rendszerében, hiszen ezeket opcionálisan más csomagkezelők is tudják alkalmazni, és egy kompatibilis környezetet összeállítani.

Fontos megjegyezni, hogy a project.dependencies táblát a Pixi a default feature-höz rendeli.

Amennyiben nem Python függőséget akarunk hozzáadni, azt megtehetjük a tool.pixi.dependencies tábla kiegészítésével. Ha ez nem conda-forge csatornát használ, azt vegyük fel a tool.pixi.workspace tábla channels listájába. További információkért látogassunk a Pixi dokumentáció megfelelő oldalára.

A pixi add parancs

Függőségeket definiálhatunk a pixi add parancs segítségével is. Ugyanakkor egyszerűbb és kevésbé ad hibázásra lehetőséget, ha magát a pyproject.toml fájlt módosítjuk. Mindenesetre az add parancs működését megtaláljuk a Pixi dokumentációban

A Pixi automatikusan fenntart egy pixi.lock fájlt, amit frissít is valamennyi Pixi parancs futtatása esetén (pl. pixi run, pixi install). Ha kifejezetten csak a lock fájlt akarjuk frissíteni a pyproject.toml változtatásai alapján, ezt megtehetjük a pixi lock parancs segítségével.

Környezetek és task-ok

Most bemutatjuk a definiált környezeteket, illetve azt, hogy mire használjuk őket. Mindenekelőtt fontos megemlíteni, hogy a default feature a rendszer alapvető futtatására van fenntartva, ahhoz nem kell semmi egyéb.

Először bemutatjuk a task-okat:

Task Leírás
start Elindítja a Python service-t
compile-cache Compile-olja a pyc fájlokat. Alapvetően sosem szükséges használni, hiszen ezek automatikusan generálódnak. Viszont az első indítást gyorsítja.
generate-api Legenerálja a DTO-kat az api repo alapján
lint Lefuttatja a linter-t (lásd. linting).
lint-autofix Lefuttatja a linter-t, miközben megpróbálja javítani az automatikusan javítható hibákat.
check-format Ellenőrzi a kódformázási hibákat (lásd. formázás).
fix-format Javítja a kódformázási hibákat.
check-code Ellenőrzi a kódot a linter és formatter segítségével. A CI/CD build job kódminőség-ellenőrzéseit utánozza.
check-imports Ellenőrzi az csomaghasználati és -definiálási hibákat (lásd. függőséghasználat).
test Unit-teszteli a kódot (lásd. unit tesztelés).
test-coverage Unit-teszteli a kódot, miközben ellenőrzi a lefedettséget.
build-coverage-report Teszt-lefedettség ellenőrzése után abból HTML jelentést épít.
show-coverage Teszt-lefedettség ellenőrzése után abból HTML jelentést épít, és megnyitja böngészőben.

default

Az alapértelmezett környezet a teljes fejlesztői infrastruktúrát tartalmazza, beleértve az összes feature-t és task-ot. Tekintve hogy a fejlesztői gépeken elég tárhely áll rendelkezésre, az összes eszköz telepítése nem okoz problémát. A környezet támogatja a Linux, Windows és ARM-alapú macOS rendszereket, ezek közül utóbbi kettő a fejlesztői laptopok operációs rendszere. Rendelkezésre áll benne a jupyter csomag is notebook-okban való kísérletezéshez.

prod

Feladata, hogy Docker konténerben futtassa a rendszert. Ennek megfelelően csak a futtatáshoz szükséges csomagokat tartalmazza (azaz default feature-t), és kizárólag a Linux rendszert támogatja. Task-okból csak a start és a compile-cache áll rendelkezésre.

prod-api

Ez a környezet nem tudja futtatni a rendszert. Csak a Linux-ot támogatja, és egyetlen használata, hogy legenerálja a DTO-kat, hogy a prod környezet tudja futtatni a rendszert (az nem tartalmazza a DTO-generáláshoz szükséges csomagokat). Egyetlen task-ja ennek megfelelően a generate-api.

cicd

Feladata, hogy futtassa CI/CD build job-ját, a kódminőséget ellenőrző feladatok kivételével. Ennek megfelelően a rendszer futtatásán kívül képes DTO-kat generálni és tesztelni is. Továbbá ebbe a környezetbe tartozik a kódminőséget érintő feladatok közül a függőséghasználat ellenőrzése (ennek oka, hogy az import-ok ellenőrzéséhez szükséges a futtatási környezet létezése, hiszen a különböző csomagneveket így lehet azonosítani).

A környezet kizárólag Linux rendszert támogat, és a csomagverziók a prod és prod-fmt környezetekkel együtt történnek rögzítésre, hogy a prod környezet esetleges hibáit a cicd környezet is felfedje.

cicd-fmt

Ez a környezet nem tudja futtatni a rendszert. Célja a kódminőség ellenőrzése a CI/CD build job-ban. Ennek megfelelően a kódformázási és lint-elési task-okat tudja végezni (a függőséghasználatot nem tudja ellenőrizni a cicd-nél leírtak miatt). Kizárólag a Linux rendszer támogatja, és a csomagverziók a prod és prod-fmt környezetekkel együtt történnek rögzítésre, hogy a build job-ban kevesebb csomagot kelljen letölteni (hiszen a cicd is ezekhez van fixálva).