A Practical Guide to Using Setup.py

Data & AI Training Guide 2021

Töltse le a GoDataDriven brosúrát a rendelkezésre álló képzések és az adatmérnöki, adattudományi, adatelemzői és analitikai fordítói tanfolyamok teljes áttekintéséhez.

Ha hivatásszerűen használja a pythont, érdemes a projektjeit
következetes módon beállítani. Ez segít a munkatársaidnak gyorsan megérteni a
projekt felépítését, és megkönnyíti számukra a
projekt beállítását a saját gépükön. A projekt beállításának kulcsa a setup.py fájl.
Ebben a blogban ennek a fájlnak a részleteire térek ki.

Honnan kezdjük

Ezzel kapcsolatban feltételezem, hogy már van egy csomagod, amit be akarsz állítani.
Ez nem kell, hogy egy kész csomag legyen – ideális esetben jóval a projekted befejezése előtt létrehozod a
setup.py fájlt. Ez akár egy üres csomag is lehet;
csak győződjön meg róla, hogy a csomag mappa létezik
és tartalmaz egy init.py nevű fájlt (ami lehet üres).

Ha követed kollégám, Henk
struktúráját
a projektedhez, a kiindulási helyzetednek valahogy így kell kinéznie:

example_project/├── exampleproject/ Python package with source code.│ ├── __init__.py Make the folder a package.│ └── example.py Example module.└── README.md README with info of the project.

A struktúrádban lehetnek más fájlok vagy mappák is, például
a notebooks/, tests/ vagy data/ nevű mappák, de ezekre nincs szükség.

Egy setup.py

Ha már létrehozott egy ilyen csomagot, akkor valószínűleg
más helyeken is használni fogja a kód egy részét. Például
a következőt akarod
megtenni egy jegyzetfüzetben:

from exampleproject.example import example_function

Ez akkor működne, ha az aktuális munkakönyvtárad example_project/, de
minden más esetben a python olyan kimenetet ad, mint:

ModuleNotFoundError: No module named 'exampleproject'

Megmondhatnád a pythonnak, hogy hol keresse a csomagot a PYTHONPATH
környezetváltozó beállításával vagy az sys.path elérési útvonalának hozzáadásával,
de ez messze nem ideális: különböző
platformokon különböző műveleteket igényelne, és a beállítandó elérési útvonal a kódod helyétől függ.
Sokkal jobb megoldás, ha a csomagodat egy setup.py és egy pip segítségével telepíted,
mivel a pip a szabványos módja az összes többi csomag telepítésének, és kötelező
minden platformon ugyanúgy működik.

Egy minimális példa

Hogyan néz ki egy setup.py fájl? Íme egy minimális példa0:

from setuptools import setup, find_packagessetup( name='example', version='0.1.0', packages=find_packages(include=))

Itt három dolgot adunk meg:

  • A csomag nevét, vagyis azt a nevet, amit pip a csomagodra fog használni.
    Ez nem kell, hogy megegyezzen a mappa nevével, amelyben a csomag él
    , bár zavaró lehet, ha nem így van. Egy példa arra, amikor a csomag
    név és a könyvtár nem egyezik, a Scikit-Learn: telepíted
    a pip install scikit-learn használatával, míg használod a sklearn-ből történő importálással.
  • A csomagod verziója. Ezt a verziót pip fogja jelenteni, és ezt használjuk
    például, amikor a csomagodat a PyPI-n publikálod1.
  • Milyen csomagokat kell bevonni; esetünkben ez csak exampleproject/.
    Itt hagyjuk, hogy setuptools ezt
    automatikusan kitalálja2. Bár elvileg használhatnánk find_packages()
    minden argumentum nélkül, ez potenciálisan azt eredményezheti, hogy nem kívánt csomagok kerülnek
    be. Ez történhet például,
    ha a tests/
    könyvtáradba egy __init__.pycsomagot vettél fel. Alternatívaként használhatja a exclude argumentumot is, hogy kifejezetten
    megakadályozza a tesztek felvételét a csomagba, de ez kissé
    kevésbé robusztus.

Most már csak annyit kell tennünk a csomag telepítéséhez, hogy a example_project/könyvtár3 belsejéből futtatjuk a következőt
:

pip install -e .

A . itt az aktuális munkakönyvtárra utal, amiről feltételezem, hogy az a könyvtár
, ahol a setup.py megtalálható. A -e flag azt adja meg, hogy szerkeszthető üzemmódban akarjuk telepíteni
, ami azt jelenti
, hogy amikor szerkesztjük a csomagunkban lévő fájlokat, nem kell újra telepítenünk a
csomagot, mielőtt a változások hatályba lépnének. Azonban vagy újra kell indítani a
python-t, vagy újra kell tölteni a csomagot!

Ha magában a setup.pyben lévő információkat szerkesztjük, a legtöbb esetben újra kell telepítenünk
a csomagot, és akkor is, ha új (al)csomagokat adunk hozzá.
Ha kétség merül fel, sosem árt az újratelepítés. Csak futtasd le újra a pip install -e ..

Követelmények

A legtöbb projektnek van néhány függősége. Valószínűleg használtál már korábban egy
a requirements.txt
fájlt, vagy egy environment.yml
fájlt, ha a conda-t használod. Most, hogy létrehoz egy setup.py-öt, a install_requires argumentumban megadhatja a
függőségeit.
Egy tipikus adattudományi projekt esetében például:

setup( name='example', version='0.1.0', packages=find_packages(include=), install_requires=)

megadhatja a követelményeket verzió nélkül (PyYAML), kitűzhet egy verziót (pandas==0.23.3), megadhat egy minimális
verziót ('numpy>=1.14.5) vagy beállíthatja a verziók tartományát (matplotlib>=2.2.0,<3.0.0). Ezeket a
követelményeket a pip automatikusan telepíti a csomag telepítésekor.

Extras-require

Néha lehetnek olyan függőségek, amelyek csak bizonyos helyzetekben szükségesek. Adatkutatóként
gyakran készítek olyan csomagokat, amelyeket egy modell betanításához használok. Amikor egy ilyen modellen dolgozom interaktívan
, szükségem lehet a matplotlib és a jupyter telepítésére, hogy interaktívan dolgozhassak az
adatokkal, és vizualizációkat készíthessek
a modell teljesítményéről. Másrészt, ha a modell termelésben fut, nem
akarom
sem a matplotlib, sem a jupyter telepíteni arra a gépre (vagy konténerre), ahol a képzést
vagy a következtetést végzem. Szerencsére a setuptools lehetővé teszi a extras_require-ben az opcionális függőségek megadását:

setup( name='example', version='0.1.0', packages=find_packages(include=), install_requires=, extras_require={ 'interactive': , })

most ha normálisan telepítjük a csomagot (pip install example a PyPI-ről vagy pip install -e . lokálisan)
ez csak a PyYAML, pandas és numpy függőségeket fogja telepíteni. Ha azonban megadjuk
, hogy az opcionális interactive függőségeket szeretnénk (pip install example
vagy pip install -e .),
akkor a matplotlib és jupyter is települni fog.

Skriptek és belépési pontok

A PyPI-ről telepített legtöbb python csomag fő felhasználási területe az, hogy olyan funkciókat
biztosít, amelyeket más python kódban használhatunk. Más szóval importezekből a csomagokból
Az adattudósként gyakran készítek olyan csomagokat, amelyek nem arra szolgálnak, hogy más python kód használja őket, hanem
azt szolgálják, hogy csináljanak valamit, például egy modellt képezzenek. Mint ilyen, gyakran van egy python szkriptem, amit
a parancssorból akarok végrehajtani.

A legjobb módja4 annak, hogy a csomagod funkcionalitását a parancssorba helyezd, ha
egy entry_point-öt így definiálsz:

setup( # ..., entry_points={ 'console_scripts': })

Most a parancssorból használhatod a my-command parancsot, ami viszont a main
funkciót fogja végrehajtani a exampleproject/example.py-ben lévő main
funkciót. Ne felejtsd el újra telepíteni – különben a
parancs nem lesz regisztrálva.

Tesztek

Amikor bármilyen kódot írsz, erősen javaslom, hogy írj teszteket is ehhez a kódhoz. A teszteléshez
pythonnal javaslom a pytest használatát. Természetesen nem érdemes a pytest-t a függőségek
beinstall_requires felvenni: a csomagod felhasználóinak nincs rá szükségük. Ahhoz, hogy a tesztek futtatásakor automatikusan települjön
, a következőket adhatod hozzá a setup.py-edhez:

setup( # ..., setup_requires=, tests_require=,)

Kiegészítésképpen létre kell hoznod egy setup.cfg nevű fájlt a következő tartalommal:

test=pytest

Ezután egyszerűen futtathatod a python setup.py test-et, és a setuptools gondoskodik arról, hogy a szükséges függőségek
telepítve legyenek, és lefuttatja helyetted a pytest-et! Nézd meg itt, ha
a pytest számára szeretnél argumentumokat megadni vagy konfigurációs opciókat beállítani.

Ha bármilyen további követelményed van a teszteléshez (pl. pytest-flask), akkor ezeket hozzáadhatod a tests_requirehez.

Flake8

Személyesen úgy gondolom, hogy jó ötlet a Flake8 futtatása, hogy
ellenőrizd a kódod formázását. A pytest-hez hasonlóan a flake8-öt sem érdemes hozzáadni a
install_requires függőségekhez: nem kell telepíteni ahhoz, hogy a
csomagodat használni tudd. Ehelyett hozzáadhatod a setup_requires:

setup( # ..., setup_requires=)

Most egyszerűen futtathatod a python setup.py flake8-et. Természetesen a flake8 (vagy bármely más csomag) setup_requires.

Változatát
a flake8 (vagy bármely más csomag) setup_requires.

Ha meg akarod változtatni a Flake8 néhány konfigurációs paraméterét, akkor egy szakaszt adhatsz a
a setup.cfg-hez. Például:

max-line-length=120

Package data

Néha előfordulhat, hogy a csomagodba néhány nem-python fájlt is be akarsz építeni. Ezek
lehetnek például sémafájlok vagy egy kis keresőtábla. Legyen tudatában annak, hogy az ilyen fájlok
a kódjával együtt lesznek becsomagolva, ezért általában rossz ötlet
bármilyen nagyméretű fájlt bevonni.

Tegyük fel, hogy van egy schema.json a projektünkben, amit a exampleproject/data/schema.json-ban helyezünk el.
Ha ezt be akarjuk építeni a csomagunkba, akkor a setup package_data argumentumát kell használnunk:

setup( # ..., package_data={'exampleproject': })

Ez biztosítja, hogy a fájl bekerüljön a csomagba. Választhatjuk azt is, hogy egy minta alapján minden
fájlt felveszünk, például:

setup( # ..., package_data={'': })

Ez minden *.json fájlt felvesz minden csomagba, amellyel találkozik.

Ne próbáld meg most magad kitalálni a telepített fájlok helyét, mivel a
pkg_resources rendelkezik néhány nagyon hasznos kényelmi funkcióval:

  • pkg_resources.resource_stream megadja a fájl folyamát, hasonlóan a
    objektumhoz, amit a open() hívásakor kapsz,
  • pkg_resources.resource_string megadja a fájl tartalmát stringként,
  • pkg_resources.resource_filename a fájl fájlnevét fogja megadni (és kivonja
    egy ideiglenesbe, ha az egy zipelt csomagban van), ha a fenti két opció
    nem felel meg az igényeidnek.

A sémánkat például a következőkkel olvashatjuk be:

from json import loadfrom pkg_resources import resource_streamschema = load(resource_stream('exampleproject', 'data/schema.json'))

Metaadatok

Ha közzé akarjuk tenni a csomagunkat, akkor valószínűleg szeretnénk a
lehetséges felhasználóknak még néhány információt megadni a csomagunkról, beleértve egy leírást,
a szerző vagy a karbantartó nevét és a csomag honlapjának url-jét.
Az összes megengedett metaadat teljes listáját megtalálod a setuptools
docsban.

Kiegészítésképpen, ha közzé fogod tenni a PyPI-n, akkor érdemes
automatikusan betölteni a README.md
tartalmát a long_descriptionba,
és osztályozókat megadni, hogy pip még
többet mondj a csomagodról.

Wrap-up

Ez a blog jó kiindulópont lehet a legtöbb python projekted beállításához.
Ha többet szeretnél olvasni a python csomagolásról, nézz
a dokumentációba. Itt van egy példa setup.py
amely egyesíti az ebben a blogban bemutatott részeket:

from setuptools import setup, find_packagessetup( name='example', version='0.1.0', description='Setting up a python package', author='Rogier van der Geer', author_email='[email protected]', url='https://blog.godatadriven.com/setup-py', packages=find_packages(include=), install_requires=, extras_require={'plotting': }, setup_requires=, tests_require=, entry_points={ 'console_scripts': }, package_data={'exampleproject': })

és a hozzá tartozó setup.cfg:

test=pytestmax-line-length=120

Visszafejleszd a Python készségeidet, tanulj a szakértőktől!

A GoDataDriven-nél számos Python tanfolyamot kínálunk a kezdőtől a szakértőig, amelyeket a terület legjobb szakemberei tanítanak. Csatlakozzon hozzánk, és fejlessze Python-játékát:

  • Python Essentials – Nagyszerű, ha még csak most kezdi a Python használatát.
  • Certified Data Science with Python Foundation – Szeretné megtenni a lépést az adatelemzéstől és vizualizációtól az igazi adattudományig? Ez a megfelelő tanfolyam.
  • Advanced Data Science with Python – Tanuld meg profiként gyártani a modelljeidet, és használd a Pythont gépi tanulásra.
Footnotes

0: Ebben a blogban a setuptools
t használtam a példaprojekt beállításához. Alternatívaként
használhatod a distutils-t is,
amely a pythonban a csomagoláshoz használt szabványos eszköz, de hiányoznak belőle olyan funkciók
, mint a find_packages() függvény és a entry_points.
Mivel a setuptools használata manapság nagyon elterjedt, és sok funkciója
különösen hasznos lehet, azt javaslom, hogy a setuptools-t használd.

1: Ha azt szeretnéd, hogy a csomagod verziója a pythonon belül is elérhető legyen,
nézd meg itt.

2: Manuálisan is listázhatod a csomagjaidat, de ez különösen hibakényes.

3: Alternatívaként futtathatod a python setup.py install, de a pip használatának
sok előnye van, többek között a függőségek automatikus telepítése és az
lehetőség a csomagod eltávolítására vagy frissítésére.

4: Használhatja a scripts argumentumot is (lásd a
példát itt)
de mivel ehhez egy python shell scriptet kell létrehoznia, lehet, hogy nem működik
olyan jól (vagy egyáltalán nem) Windowson.

Felületen
nem működik.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.