Package: hellopypa
Hogyan készítsünk python csomagot1. Bevezetés2. Könyvtárszerkezet3. Környezet4. Az__init__.pyfájl5. Tesztelés6. Asetup.pyfájl7. További lehetőségek7.1. Verzió7.2. Fájlok hozzáadása7.3. Parancssori futtatásTODOIrodalom1. BevezetésAmodul(module) egy python fájl, ami importálható, névteret alkot és tetszőleges további python objektumokat tartalmazhat.Acsomag(package) egy olyan könyvtár, ami tartalmaz egy__init__.pyfájlt, továbbá tartalmazhat további alcsomagokat (alkönyvtárakat) és
modulokat (python fájlokat). Acsomagis importálható, névteret alkot és
további python objektumokat tartalmazhat.Megjegyzés: Amodul~fájlés acsomag~könyvtárcsak analógia, nem minden
esetben igaz. Részletekitt.A csomagokat a Python csomagkezelőjével, apip-pel lehet telepíteni, frissíteni,
eltávolítani. Apipképes verziókezelő repozitóriumokból is telepíteni, így
pl. a Github-ról is, de a python csomagok publikálásának szokott módja a
csomag feltöltése apypi.org-ra (PyPI: Python Package
Index). Ennek mikéntjéről lesz szó az alábbiakban.Apypi.org-ot és a csomagoláshoz szükséges eszközöket aPyPA(Python Packaging Authority) fejleszti és tartja karban. Honlapjukon
(pypa.io) sok hasznos anyag elérhető
csomagolás és terjesztés témakörben.2. Könyvtárszerkezethellopypa/
    hellopypa/
        __init__.py
        __main__.py
        example.cfg
        hellopypa.py
        version.py
    test/
        __init__.py
        test_hello.py
    LICENSE
    MANIFEST.in
    README.md
    requirements.txt
    requirements-dev.txt
    setup.pyFontosabb könyvtárak és fájlok:hellopypa/: A csomagunk fő könyvtára. Általában jó, ha ez megegyezik
magának a repónak a nevével (külsőhellopypa/könyvtár), de nem szükséges.test/: A csomaghoz való tesztek könyvtára. A tesztek nem részei a
csomagnak, csak a repónak.LICENSE: Licenc, a lehetőségeket l.ittésitt, további tanácsokitt.MANIFEST.in: Itt soroljuk fel a csomaghoz tartozó nem python fájlokat (binárisok, konfig fájlok, stb).README.md: Readme fájl, röviden leírja, hogy mire jó a csomag, hogyan kell telepíteni és hogyan lehet futtatni. Amarkdownformátumról bővebbenitt, a tartalmárólittlehet olvasni.requirements*.txt: Ezekben vannak felsorolva azok a python csomagok, amelyeket használunk (függőségek). Arequirements.txttartalmazza magának a csomagnak a függőségeit, arequirements-dev.txtpedig a fejlesztéshez szükséges függőségeket (tesztelés, linter, stb).setup.py: Ez a fájl tartalmazza csomagoláshoz kellő metaadatokat.3. KörnyezetHozzunk létre a csomagnak külön virtuális környezetet és aktiváljuk
(részletekittésitt):python3 -m venv .venv
source .venv/bin/activateTelepítsük a csomaghoz (requirements.txt) valamint a csomagoláshoz és
fejlesztéshez szükséges függőségeket (requirements-dev.txt):pipinstall-rrequirements-dev.txtMegjegyzés: Arequirements-dev.txtimportálja simarequirements.txt-t is.
Arequirements.txtfájlok leírását l.ittésitt.A csomagoláshoz az alábbi csomagok szükségesek:setuptools: Ez asetup.pyfüggősége.twine: Ezzel lehet apypi.org-ra feltölteni az
elkészült csomagot.wheel: Ez kell a 2012-ben bevezetettwheelcsomagformátumhoz (l.PEP
427).4. Az__init__.pyfájlAz__init__.pylehet üres is, de ekkor is léteznie kell. Ha nem üres, akkor
a csomag importálásánál a tartalma végrehajtódik. Szokás a metaadatok és az
API meghatározására használni.Metaadatok: Kisebb projekteknél itt lehet felsorolni a csomag szerzőit,
verzióját, licencét, megadni email-címet, karbantartót, hálát kifejezni a
hozzájárulóknak, stb. Részletekitt. A
verziót érdemes külön fájlban tartani, l. alább aVerziófejezetet.API: Alapesetben ha használni szeretnénk egy importált csomag egy függvényét,
akkor azt így tudjuk hívni:csomag[.alcsomag].fájl.függvény()Ebből acsomag-ot és afüggvény-t nem lehet elhagyni, de azalcsomagés
afájláltalában felesleges. A felhasználónak csak azt kellene
megjegyeznie, hogy melyik függvény melyik csomagban van, azt nem, hogy melyik
csomag melyik fájljában van. Ráadásul a csomag írói is szeretik a kódot
rugalmasan átszervezni a háttérben, pl. egy nagyra nőtt fájl egy részét
új fájlba írni anélkül, hogy eltörnék azAPI-t.Mivel az__init__.py-ban található kód importáláskor végrehajtódik,
ezért érdemes itt importálni a publikusnak szánt függvényeket, osztályokat, ezzel a csomag importálásakor ezek az objektumok is közvetlenül használhatók lesznek. Példa:# mypackage/__init__.pyfromfile1importfunction1,function2fromfile2importfunction3Ezután a használat egyszerű:importmypackagemypackage.function1()Megjegyzés: Ha az__init__.py-ban csillaggal importálunk (from file import *), akkor az alulvonással kezdődő objektumok nem kerülnek
importálásra (a teljes elérési útjukon keresztül továbbra is elérhetőek
lesznek, részletekitt).5. TesztelésMielőtt csomagolnánk, teszteljük le az alkalmazásunkat. A teszteléshez
használhatjuk a hagyományosunittest-et, vagy az
újabban elterjedtpytest-et. Atest/könyvtárban vannak a tesztfájlok, ezeketpytestestén a következő
paranccsal futtathatjuk:pytest--verbosetest/Megjegyzés: atest/könyvtár maga is csomag, kell benne lennie__init__.pyfájlnak.6. Asetup.pyfájlMagát a csomagolást (a terjeszthető és telepíthető formátum létrehozását) asetuptoolsnevű python
csomag végzi. Asetup.pyfájl tartalmazza asetuptoolsszámára szükséges
adatokat. Az adatokat lehet közvetlenül asetup.py-ba is beírni, de néha
hasznosabb máshol tárolni az adatot és asetup.py-ban csak importálni, vagy
más módon beolvasni.Egy viszonylag minimalista példa:importsetuptoolswithopen('README.md','r')asfh:long_description=fh.read()setuptools.setup(name='csomagnév',version='0.0.1',author='szerző',description='Minimalista példa csomag',long_description=long_description,long_description_content_type='text/markdown',url='https://github.com/szerző/csomagnév',packages=setuptools.find_packages(exclude=['test']),classifiers=['Programming Language :: Python :: 3','License :: OSI Approved :: MIT License','Operating System :: POSIX :: Linux',],python_requires='>=3.6',)Asetuptools.setupfontosabb mezői:name: A csomag neve (kötelező).version: A csomag verziója (kötelező). A pypi.org-ra nem lehet kétszer
ugyanazt a verziószámú csomagot feltölteni, akkor sem, ha amúgy különböznek.author: A csomag szerzője.description: Rövid leírás.long_description: Hosszú leírás, jellemzően magát a README.md-t szokták
megadni. A PyPI ezt fogja a csomag oldalán megjeleníteni. Hamarkdownfájlt
adunk meg, akkor meg kell adnunk a formátumot is
(.rstaz alapértelmezett).url: A projekt honlapja.packages: Itt adható meg, hol keresse a python fájlokat. Érdemes asetuptoolsfind_packages()függvényére bízni a dolgot. Azexclude=[dir1, dir2, ...]paraméternek megadott könyvtárakban nem fog keresni.classifiers: A PyPI számára megadható címkék listájaitt.python_requires: Megadható a minimum python verzió.Futtassuk asetup.pyfájlt:python3setup.pysdistbdist_wheelA repónkban három új könyvtár fog létrejönni: egybuild/, egydist/és
egycsomagnév.egg-info/(érdemes ezeket a.gitignorefájlba felvenni,
vagy a GitHub python-hoz írt.gitignorefájljáthasználni). Ezek közül adist/ami fontos, ebben található ugyanis a
csomagunk terjeszthető és telepíthető változata.A csomag közvetlenül telepíthető apip install .paranccal, vagy
regisztrációt követően feltölthető a pypi.org oldalra a következő paranccsal:python3-mtwineuploaddist/*Ezután bármelyik gépen telepíthető a csomag apip install csomagnévparanccsal.A pypi.org oldalnak van egy teszt változata is, ha csak kísérletezni
szeretnénk, javasolt ezt használni. A fenti parancsok ekkor így módosulnak:twineupload--repository-urlhttps://test.pypi.org/legacy/dist/*
pipinstall--index-urlhttps://test.pypi.org/simple/hellopypa7. További lehetőségekTovábbi tanácsok és lehetőségek a terjeszthető csomag testreszabására.7.1. VerzióA csomag verzióját érdemes egy helyen tárolni csak és máshol csak innen beolvasni. A lehetőségeket l.itt. Az alábbi megoldás lényege, hogy a csomagon belül egy külön fájlt használunk erre (hellopypa/version.py). Ezt a fájlt importáljuk asetup.py-ban és ahellopypa/__init__.py-ban is. Ezzel elkerülhetők ahellopypa/__init__.pyközvetlen importálásának problémái (l. az előbbi cikk 6. pontjához írt figyelmeztetést), de telepítés nélkül is hozzáférhető lesz a verzió, mintha az__init__.py-ban lenne közvetlenül.# hellopypa/version.py__version__='0.0.3'# hellopypa/__init__.py# ...fromhellopypa.versionimport__version__# ...# setup.py# ...fromhellopypa.versionimport__version__# ...setuptools.setup(# ...version=__version__,# ...)7.2. Fájlok hozzáadásaAsetuptoolscsak a python fájlokat veszi figyelembe. Ha más fájlokat is a
csomaghoz szeretnénk adni (konfigurációs fájlokat, binárisokat, adatot),
akkor két dolgot kell csinálnunk.Létre kell hoznunk egyMANIFEST.infájlt, amiben felsoroljuk, hogy miket
szeretnénk még a csomaghoz adni. Részletekitt. Példa: adjuk a
projekthez a.cfgkiterjesztésű fájlokat.# MANIFEST.in
include hellopypa/*.cfgAsetup.py-ba is bele kell írni, hogy további fájlok is lesznek.# setup.py# ...setuptools.setup(# ...include_package_data=True,# ...)7.3. Parancssori futtatásHa csomagunkat apip install hellopypaután nem csak importálva, de
parancssori alkalmazásként is szeretnénk használni, akkor két dolgot
tehetünk.Egy python csomag futtatható az-mkapcsolóval (pl.# python -m hellopypa). Ehhez az kell, hogy a csomagban legyen egy__main__.pyfájl, a
python ezt fogja keresni és ha létezik, akkor futtatni. Részletek (nem mintha
nagyon lennének)itt.Egy python csomag futtatható rendes, telepített parancsként is (pl.# hellopypa). Ekkor asetup.py-ban meg kell adni egy úgynevezett belépési
pontot, konkrétan egy függvényt, amit meg fog hívni a python. Részletekitt.
Példa:# setup.py# ...setuptools.setup(# ...entry_points={"console_scripts":["hellopypa=hellopypa.__main__:main",]},# ...)8. MakeÁtmeneti megoldás, amíg nincs rendes automatizálás.make clean: A build-elés során keletkezett könyvtárak törlése (buld/,dist/,*.egg-info/).make test: Tesztek futtatása.make build: Build-elés.make release_major:Majorverziószám váltás, új release a GitHub-on és a
PyPI-n.make release_minor:Minorverziószám váltás, új release a GitHub-on és a
PyPI-n.make release_patch:Patchverziószám váltás, új release a GitHub-on és a
PyPI-n.TODOTartalomBevezetés: modul, csomag, pypiKönyvtárszerkezetKörnyezetTesztelésDokumentációAsetup.pyfájlAMANIFEST.infájl__main__.py, CLI__init__.py, APIVerziózásCsomagolásKözzétételAutomatizálásTelepítéslokálisanpypimakefüggőség buildelése a setup.py használatával???függőség letöltése telepítéskor???IrodalomPyPA gyorstalpalója:https://packaging.python.org/tutorials/packaging-projects/PyPA útmutatói egyes témákhoz:https://packaging.python.org/guides/Real Pythontutorial:https://realpython.com/pypi-publish-python-package/setuptoolsdokumentáció:https://setuptools.readthedocs.io/en/latest/