A sample Python package
Project description
Hogyan készítsünk python csomagot
- 1. Bevezetés
- 2. Könyvtárszerkezet
- 3. Környezet
- 4. Az
__init__.py
fájl - 5. Tesztelés
- 6. A
setup.py
fájl - 7. További lehetőségek
- TODO
- Irodalom
1. Bevezetés
A modul (module) egy python fájl, ami importálható, névteret alkot és tetszőleges további python objektumokat tartalmazhat.
A csomag (package) egy olyan könyvtár, ami tartalmaz egy __init__.py
fájlt, továbbá tartalmazhat további alcsomagokat (alkönyvtárakat) és
modulokat (python fájlokat). A csomag is importálható, névteret alkot és
további python objektumokat tartalmazhat.
Megjegyzés: A modul~fájl és a csomag~könyvtár csak analógia, nem minden esetben igaz. Részletek itt.
A csomagokat a Python csomagkezelőjével, a
pip
-pel lehet telepíteni, frissíteni,
eltávolítani. A pip
ké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 a pypi.org-ra (PyPI: Python Package
Index). Ennek mikéntjéről lesz szó az alábbiakban.
A pypi.org-ot és a csomagoláshoz szükséges eszközöket a PyPA (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árszerkezet
hellopypa/
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.py
Fontosabb 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 és itt, további tanácsok itt.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. A markdown formátumról bővebben itt, a tartalmáról itt lehet olvasni.requirements*.txt
: Ezekben vannak felsorolva azok a python csomagok, amelyeket használunk (függőségek). Arequirements.txt
tartalmazza magának a csomagnak a függőségeit, arequirements-dev.txt
pedig 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örnyezet
Hozzunk létre a csomagnak külön virtuális környezetet és aktiváljuk (részletek itt és itt):
python3 -m venv .venv
source .venv/bin/activate
Telepítsük a csomaghoz (requirements.txt
) valamint a csomagoláshoz és
fejlesztéshez szükséges függőségeket (requirements-dev.txt
):
pip install -r requirements-dev.txt
Megjegyzés: A requirements-dev.txt
importálja sima requirements.txt
-t is.
A requirements.txt
fájlok leírását l.
itt
és itt.
A csomagoláshoz az alábbi csomagok szükségesek:
setuptools
: Ez asetup.py
függősége.twine
: Ezzel lehet a pypi.org-ra feltölteni az elkészült csomagot.wheel
: Ez kell a 2012-ben bevezetett wheel csomagformátumhoz (l. PEP 427).
4. Az __init__.py
fájl
Az __init__.py
lehet ü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észletek itt. A verziót érdemes külön fájlban tartani, l. alább a Verzió 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 a csomag
-ot és a függvény
-t nem lehet elhagyni, de az alcsomag
és
a fá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 az API-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__.py
from file1 import function1, function2
from file2 import function3
Ezután a használat egyszerű:
import mypackage
mypackage.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észletek
itt).
5. Tesztelés
Mielőtt csomagolnánk, teszteljük le az alkalmazásunkat. A teszteléshez
használhatjuk a hagyományos
unittest-et, vagy az
újabban elterjedt pytest-et. A
test/
könyvtárban vannak a tesztfájlok, ezeket pytest estén a következő
paranccsal futtathatjuk:
pytest --verbose test/
Megjegyzés: a test/
könyvtár maga is csomag, kell benne lennie
__init__.py
fájlnak.
6. A setup.py
fájl
Magát a csomagolást (a terjeszthető és telepíthető formátum létrehozását) a
setuptools nevű python
csomag végzi. A setup.py
fájl tartalmazza a setuptools számára szükséges
adatokat. Az adatokat lehet közvetlenül a setup.py
-ba is beírni, de néha
hasznosabb máshol tárolni az adatot és a setup.py
-ban csak importálni, vagy
más módon beolvasni.
Egy viszonylag minimalista példa:
import setuptools
with open('README.md', 'r') as fh:
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',
)
A setuptools.setup fontosabb 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. Ha markdown fájlt adunk meg, akkor meg kell adnunk a formátumot is (.rst az alapértelmezett).url
: A projekt honlapja.packages
: Itt adható meg, hol keresse a python fájlokat. Érdemes a setuptoolsfind_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ája itt.python_requires
: Megadható a minimum python verzió.
Futtassuk a setup.py
fájlt:
python3 setup.py sdist bdist_wheel
A repónkban három új könyvtár fog létrejönni: egy build/
, egy dist/
és
egy csomagnév.egg-info/
(érdemes ezeket a .gitignore
fájlba felvenni,
vagy a GitHub python-hoz írt .gitignore
fájlját
használni). Ezek közül a dist/
ami fontos, ebben található ugyanis a
csomagunk terjeszthető és telepíthető változata.
A csomag közvetlenül telepíthető a pip install .
paranccal, vagy
regisztrációt követően feltölthető a pypi.org oldalra a következő paranccsal:
python3 -m twine upload dist/*
Ezután bármelyik gépen telepíthető a csomag a pip install csomagnév
paranccsal.
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:
twine upload --repository-url https://test.pypi.org/legacy/ dist/*
pip install --index-url https://test.pypi.org/simple/ hellopypa
7. További lehetőségek
Tová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 a setup.py
-ban és a hellopypa/__init__.py
-ban is. Ezzel elkerülhetők a hellopypa/__init__.py
kö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
# ...
from hellopypa.version import __version__
# ...
# setup.py
# ...
from hellopypa.version import __version__
# ...
setuptools.setup(
# ...
version=__version__,
# ...
)
7.2. Fájlok hozzáadása
A setuptools csak 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 egy MANIFEST.in fájlt, amiben felsoroljuk, hogy miket szeretnénk még a csomaghoz adni. Részletek itt. Példa: adjuk a projekthez a .cfg kiterjesztésű fájlokat.
# MANIFEST.in include hellopypa/*.cfg
-
A setup.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ás
Ha csomagunkat a pip install hellopypa
utá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
-m
kapcsolóval (pl.# python -m hellopypa
). Ehhez az kell, hogy a csomagban legyen egy__main__.py
fá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 a setup.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észletek itt. 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
: Major verziószám váltás, új release a GitHub-on és a
PyPI-n.
make release_minor
: Minor verziószám váltás, új release a GitHub-on és a
PyPI-n.
make release_patch
: Patch verziószám váltás, új release a GitHub-on és a
PyPI-n.
TODO
- Tartalom
- Bevezetés: modul, csomag, pypi
- Könyvtárszerkezet
- Környezet
- Tesztelés
- Dokumentáció
- A
setup.py
fájl - A
MANIFEST.in
fájl -
__main__.py
, CLI -
__init__.py
, API - Verziózás
- Csomagolás
- Közzététel
- Automatizálás
- Telepítés
- lokálisan
- pypi
- make
- függőség buildelése a setup.py használatával???
- függőség letöltése telepítéskor???
Irodalom
- PyPA gyorstalpalója: https://packaging.python.org/tutorials/packaging-projects/
- PyPA útmutatói egyes témákhoz: https://packaging.python.org/guides/
- Real Python tutorial: https://realpython.com/pypi-publish-python-package/
- setuptools dokumentáció: https://setuptools.readthedocs.io/en/latest/
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file hellopypa-0.0.11.tar.gz
.
File metadata
- Download URL: hellopypa-0.0.11.tar.gz
- Upload date:
- Size: 10.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | a9e3b9af4af51c84b47438acc71cc9efed634782a6992dd61d22b4a89e6ae9ad |
|
MD5 | 389d94f616d39d60590be94f3e0a9344 |
|
BLAKE2b-256 | 232f1328fde7d57c2db21c12ce6f215c5c338933352719e522464735eff7e197 |
File details
Details for the file hellopypa-0.0.11-py3-none-any.whl
.
File metadata
- Download URL: hellopypa-0.0.11-py3-none-any.whl
- Upload date:
- Size: 9.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.7.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 93ea1120cc0ab40eb1c0dc11d76eb80e2f5389f2ed601a27340ff26bccd6caca |
|
MD5 | ddd64afd584e28816ae88500e9367398 |
|
BLAKE2b-256 | a3a39b15ff6eac829ccbcdf563ed5d0fcf0f881573d9ff3d9056397a16026731 |