Praktický průvodce používáním Setup.py

Data & Průvodce školením AI 2021

Stáhněte si brožuru GoDataDriven, kde najdete kompletní přehled dostupných školení a vzdělávacích cest datového inženýrství, datové vědy, datových analytiků a překladatelů analytiky.

Pokud používáte Python profesionálně, vyplatí se nastavit své projekty
důsledně. To pomůže vašim spolupracovníkům rychle pochopit
strukturu projektu a usnadní jim to nastavení projektu
na jejich počítači. Klíčem k nastavení projektu je soubor setup.py.
V tomto blogu se budu věnovat podrobnostem tohoto souboru.

Kde začneme

Předpokládám, že již máte balíček, který chcete nastavit.
Nemusí to být hotový balíček – v ideálním případě byste měli vytvořit soubor
setup.py dlouho před dokončením projektu. Může to být i prázdný balíček;
jen se ujistěte, že složka balíčku existuje
a obsahuje soubor s názvem init.py(který může být prázdný).

Pokud se budete řídit strukturou
projektu mého kolegy Henka, měla by vaše výchozí situace vypadat nějak takto:

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.

Můžete mít ve své struktuře další soubory nebo složky, například
složky s názvem notebooks/, tests/ nebo data/, ale ty nejsou nutné.

Případ pro setup.py

Jakmile vytvoříte takový balíček, pak pravděpodobně
použijete některý z kódů na jiných místech. Například byste mohli chtít
v zápisníku udělat toto:

from exampleproject.example import example_function

Toto by fungovalo, pokud je váš aktuální pracovní adresář example_project/, ale ve
všech ostatních případech vám python poskytne výstup jako např:

ModuleNotFoundError: No module named 'exampleproject'

Mohli byste pythonu říct, kde má balíček hledat, nastavením proměnné PYTHONPATH
prostředí nebo přidáním cesty do sys.path,
ale to není zdaleka ideální: na různých
platformách by to vyžadovalo různé akce a cesta, kterou musíte nastavit, závisí na umístění vašeho kódu.
Daleko lepší způsob je nainstalovat váš balíček pomocí setup.py a pip,
protože pip je standardní způsob instalace všech ostatních balíčků a je vázán
na to, že bude fungovat na všech platformách stejně.

Minimální příklad

Jak tedy vypadá soubor setup.py? Zde je minimální příklad0:

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

Zde uvádíme tři věci:

  • Jméno balíčku, což je jméno, které bude pippoužívat váš balíček.
    To nemusí být stejné jako jméno složky, ve které balíček žije
    , i když to může být matoucí, pokud tomu tak není. Příkladem, kdy se název balíčku
    a adresář neshodují, je Scikit-Learn: nainstalujete ho
    pomocí pip install scikit-learn, zatímco ho použijete importem z sklearn.
  • Verze vašeho balíčku. Tuto verzi bude hlásit pip a používá se
    například při publikování balíčku na PyPI1.
  • Jaké balíčky zahrnout; v našem případě je to právě exampleproject/.
    Tady to necháme setuptoolsvyřešit
    automaticky2. I když byste v zásadě mohli použít find_packages()
    bez jakýchkoli argumentů, může to potenciálně vést k zahrnutí nežádoucích balíčků
    . To se může stát například tehdy,
    pokud jste do adresáře tests/
    zařadili __init__.py. Alternativně můžete také použít argument exclude, abyste explicitně
    zabránili zahrnutí testů do balíčku, ale to je o něco
    méně robustní.

Nyní vše, co musíte udělat pro instalaci balíčku, je spustit následující příkaz
zevnitř adresáře example_project/3:

pip install -e .

Příkaz . zde odkazuje na aktuální pracovní adresář, což předpokládám, že je adresář
, kde lze nalézt setup.py. Příznak -e určuje, že chceme instalovat
v upravitelném režimu, což znamená
, že když upravíme soubory v našem balíčku, nemusíme balíček
znovu instalovat, než se změny projeví. Budete však muset buď restartovat
python, nebo balíček znovu načíst!“

Pokud upravujete informace v samotném setup.pybalíčku, budete muset ve většině případů znovu nainstalovat
balíček, a také pokud přidáváte nové (pod)balíčky.
Pokud máte pochybnosti, nikdy není na škodu balíček znovu nainstalovat. Stačí znovu spustit pip install -e ..

Požadavky

Většina projektů má nějaké závislosti. S největší pravděpodobností jste již dříve použili
soubor requirements.txt
nebo environment.yml
, pokud používáte conda. Nyní, když vytváříte setup.py, můžete zadat své
závislosti v argumentu install_requires.
Například pro typický projekt datové vědy můžete mít:

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

Můžete zadat požadavky bez verze (PyYAML), připnout verzi (pandas==0.23.3), určit minimální
verzi ('numpy>=1.14.5) nebo nastavit rozsah verzí (matplotlib>=2.2.0,<3.0.0). Tyto
požadavky budou při instalaci balíčku automaticky nainstalovány pip.

Dodatečné požadavky

Někdy můžete mít závislosti, které jsou vyžadovány pouze v určitých situacích. Jako datový vědec
často vytvářím balíčky, které používám k trénování modelu. Když na takovém modelu pracuji interaktivně
, mohu potřebovat mít nainstalované balíčky matplotlib a jupyter, abych mohl interaktivně pracovat s
daty a vytvářet vizualizace
výkonnosti modelu. Na druhou stranu, pokud model běží v produkci, nechci
instalovat matplotlib ani jupyter na stroj (nebo kontejner), kde trénuji
nebo provádím inferenci. Naštěstí setuptools umožňuje zadat volitelné závislosti v extras_require:

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

Nyní, pokud balík nainstalujeme normálně (pip install example z PyPI nebo pip install -e . lokálně)
, nainstalují se pouze závislosti PyYAML, pandas a numpy. Když však zadáme
, že chceme volitelné závislosti interactive (pip install example
nebo pip install -e .),
tak se nainstalují také matplotlib a jupyter.

Skripty a vstupní body

Hlavním případem použití většiny balíčků Python, které se instalují z PyPI, je poskytnutí funkcí
, které lze použít v jiném kódu Pythonu. Jinými slovy, můžete importz těchto balíčků
jako datový vědec často vytvářím balíčky, které nejsou určeny k použití v jiném kódu Pythonu, ale
jsou určeny k tomu, aby něco dělaly, například trénovaly model. Jako takový mám často pythonovský skript, který
chci spustit z příkazového řádku.

Nejlepším způsobem4, jak vystavit funkčnost svého balíčku příkazovému řádku, je definovat
funkci entry_point takto:

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

Nyní můžete z příkazového řádku použít příkaz my-command, který následně spustí funkci main
uvnitř exampleproject/example.py. Nezapomeňte na přeinstalaci – jinak nebude příkaz
zaregistrován.

Testy

Kdykoli budete psát jakýkoli kód, důrazně vám doporučuji, abyste pro tento kód napsali také testy. Pro testování
při použití jazyka python doporučuji použít pytest. Samozřejmě nechcete přidávat pytest do svých závislostí
v install_requires: není vyžadován uživateli vašeho balíčku. Aby se instaloval
automaticky při spouštění testů, můžete do svého setup.py přidat následující:

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

Dále budete muset vytvořit soubor s názvem setup.cfg s následujícím obsahem:

test=pytest

Nyní můžete jednoduše spustit python setup.py test a setuptools zajistí, že potřebné závislosti
budou nainstalovány a spustí pytest za vás! Podívejte se sem, pokud
chcete zadat argumenty nebo nastavit konfigurační možnosti pro pytest.

Pokud máte nějaké další požadavky na testování (např. pytest-flask), můžete je přidat do tests_require.

Flake8

Osobně si myslím, že je dobrý nápad spustit Flake8 pro
kontrolu formátování vašeho kódu. Stejně jako u pytest není vhodné přidávat flake8 do závislostí
install_requires: pro použití vašeho
balíčku nemusí být nainstalován. Místo toho jej můžete přidat do setup_requires:

setup( # ..., setup_requires=)

Nyní můžete jednoduše spustit python setup.py flake8. Samozřejmě můžete také připnout verzi
balíčku flake8 (nebo jakéhokoli jiného balíčku) do setup_requires.

Pokud chcete změnit některé konfigurační parametry Flake8, můžete do
svého setup.cfgpřidat sekci . Například:

max-line-length=120

Data balíčku

Někdy můžete chtít do svého balíčku zahrnout některé soubory, které nejsou v jazyce Python. Mohou to být například
soubory se schématy nebo malá vyhledávací tabulka. Uvědomte si, že takové soubory
budou zabaleny společně s vaším kódem, takže je obecně špatný nápad zahrnovat
jakékoli velké soubory.

Předpokládejme, že v našem projektu máme schema.json, který umístíme do exampleproject/data/schema.json.
Pokud jej chceme zahrnout do našeho balíčku, musíme použít package_dataargument setup:

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

Tím zajistíme, že soubor bude do balíčku zahrnut. Můžeme také zvolit zahrnutí
všech souborů na základě vzoru, například:

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

Tím se přidají všechny *.json soubory v každém balíčku, na který narazí.

Nyní se nesnažte sami zjistit umístění nainstalovaných souborů, protože
pkg_resources má několik velmi užitečných pomocných funkcí:

  • pkg_resources.resource_stream vám poskytne proud souboru, podobně jako
    objekt, který dostanete při volání open(),
  • pkg_resources.resource_string vám poskytne obsah souboru jako řetězec,
  • pkg_resources.resource_filename vám poskytne název souboru (a rozbalí
    jej do dočasného souboru, pokud je součástí zazipovaného balíčku) pro případ, že vám výše uvedené dvě možnosti
    nevyhovují.

Například bychom mohli načíst naše schéma pomocí:

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

Metadata

Pokud se chystáte svůj balíček publikovat, pak pravděpodobně budete chtít poskytnout svým
potenciálním uživatelům další informace o svém balíčku, včetně popisu,
jména autora nebo správce a url na domovskou stránku balíčku.
Úplný seznam všech povolených metadat najdete v setuptools
dokumentech.

Pokud se chystáte publikovat na PyPI, pak můžete
automaticky načíst obsah svého README.md
do long_description,
a poskytnout klasifikátory, které o vašem balíčku řeknou pipještě více
.

Zabalení

Tento blog by měl být dobrým výchozím bodem pro nastavení většiny vašich projektů v Pythonu.
Pokud si chcete přečíst více o balení v Pythonu, podívejte se
do dokumentace. Zde je příklad setup.py
který kombinuje všechny části uvedené v tomto blogu:

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': })

a doprovodný setup.cfg:

test=pytestmax-line-length=120

Zlepšete své znalosti Pythonu, učte se od odborníků!“

V GoDataDriven nabízíme řadu kurzů Pythonu od začátečníků až po experty, které vedou ti nejlepší profesionálové v oboru. Přidejte se k nám a zvyšte svou úroveň v Pythonu:

  • Python Essentials – Skvělé, pokud s Pythonem teprve začínáte.
  • Certified Data Science with Python Foundation – Chcete udělat krok od analýzy a vizualizace dat ke skutečné datové vědě? To je ten správný kurz.
  • Advanced Data Science with Python – Naučte se produkovat své modely jako profesionál a používat Python pro strojové učení.
Poznámky

0: V tomto blogu jsem použil setuptools
pro nastavení svého příkladového projektu. Alternativně
můžete také použít distutils,
který je standardním nástrojem pro tvorbu balíčků v Pythonu, ale chybí mu funkce
jako například funkce find_packages()a entry_points.
Protože používání nástroje setuptools je v dnešní době velmi rozšířené a mnoho jeho funkcí
může být obzvláště užitečných, doporučuji vám použít setuptools.

1: Pokud chcete, aby verze vašeho balíčku byla dostupná i uvnitř pythonu,
podívejte se sem.

2: Své balíčky můžete také vypsat ručně, ale to je obzvláště náchylné k chybám.

3: Alternativně můžete spustit python setup.py install, ale použití pip
mnoho výhod, mezi které patří automatická instalace závislostí a
možnost odinstalovat nebo aktualizovat váš balíček.

4: Mohli byste také použít argument scripts (viz například
příklad zde)
ale protože to vyžaduje vytvoření shellového skriptu Python, nemusí to v systému Windows fungovat
tak dobře (nebo vůbec).

.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.