Un ghid practic de utilizare a programului Setup.py

Date & AI Training Guide 2021

Încărcați broșura GoDataDriven pentru o prezentare completă a sesiunilor de formare disponibile și a călătoriilor de învățare pentru ingineria datelor, știința datelor, analistul de date și traducătorul analitic.

Când folosiți python în mod profesional, merită să vă configurați proiectele
într-un mod coerent. Acest lucru îi ajută pe colaboratorii dvs. să înțeleagă rapid structura
unui proiect și le este mai ușor să configureze proiectul
pe mașina lor. Cheia pentru configurarea proiectului este fișierul setup.py.
În acest blog voi intra în detaliile acestui fișier.

De unde începem

Aici presupun că aveți deja un pachet pe care doriți să îl configurați.
Nu este necesar ca acesta să fie un pachet finalizat – în mod ideal, ar trebui să creați fișierul
setup.py cu mult înainte ca proiectul dumneavoastră să fie finalizat. Ar putea fi chiar un pachet gol;
asigurați-vă doar că dosarul pachetului există
și conține un fișier numit init.py (care poate fi gol).

Dacă urmați structura colegului meu Henk
pentru proiectul dvs., situația dvs. de pornire ar trebui să arate cam așa:

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.

Puteți avea și alte fișiere sau foldere în structura dvs., de exemplu
folderele numite notebooks/, tests/ sau data/, dar acestea nu sunt necesare.

Cazul pentru un setup.py

După ce ați creat un astfel de pachet, atunci este probabil
să folosiți o parte din cod în alte locuri. De exemplu, s-ar putea să doriți
să faceți acest lucru într-un caiet de notițe:

from exampleproject.example import example_function

Acest lucru ar funcționa dacă directorul dvs. de lucru curent este example_project/, dar în
toate celelalte cazuri python vă va da un rezultat de genul:
:

ModuleNotFoundError: No module named 'exampleproject'

Ați putea să-i spuneți lui python unde să caute pachetul prin setarea variabilei PYTHONPATH
de mediu sau prin adăugarea căii la sys.path,
dar acest lucru este departe de a fi ideal: ar necesita acțiuni diferite pe diferite
platforme, iar calea pe care trebuie să o setați depinde de locația codului dvs.
O modalitate mult mai bună este să vă instalați pachetul folosind un setup.py și pip,
din moment ce pip este modul standard de instalare a tuturor celorlalte pachete, și este obligat
să funcționeze la fel pe toate platformele.

Un exemplu minimal

Acum arată un fișier setup.py? Iată un exemplu minimal0:

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

Aici specificăm trei lucruri:

  • Numele pachetului, care este numele pe care pip îl va folosi pentru pachetul dumneavoastră.
    Nu trebuie să fie același cu numele folderului în care trăiește pachetul
    , deși poate fi confuz dacă nu este. Un exemplu de situație în care numele pachetului
    și numele directorului nu se potrivesc este Scikit-Learn: îl instalați
    folosind pip install scikit-learn, în timp ce îl folosiți importându-l din sklearn.
  • Versiunea pachetului dumneavoastră. Aceasta este versiunea pe care o va raporta pip și este folosită
    de exemplu atunci când vă publicați pachetul pe PyPI1.
  • Ce pachete să includeți; în cazul nostru este doar exampleproject/.
    Aici îl lăsăm pe setuptools să își dea seama de acest lucru
    automat2. Deși, în principiu, ați putea folosi find_packages()
    fără niciun argument, acest lucru poate avea ca rezultat potențial includerea unor pachete nedorite
    . Acest lucru se poate întâmpla, de exemplu,
    dacă ați inclus un __init__.py în directorul tests/
    . Alternativ, puteți utiliza, de asemenea, argumentul exclude pentru a împiedica în mod explicit
    includerea testelor în pachet, dar acest lucru este puțin
    mai puțin robust.

Acum tot ce trebuie să faceți pentru a instala pachetul este să rulați următoarele
din interiorul example_project/directorului3:

pip install -e .

Directorul . se referă aici la directorul de lucru curent, pe care presupun că este directorul
în care se găsește setup.py. Stegulețul -e specifică faptul că dorim să instalăm
în modul editabil, ceea ce înseamnă
că atunci când modificăm fișierele din pachetul nostru nu trebuie să reinstalăm pachetul
înainte ca modificările să intre în vigoare. Totuși, va trebui fie să reporniți
python, fie să reîncărcați pachetul!

Când editați informații în setup.py însuși, va trebui să reinstalați
pachetul în majoritatea cazurilor și, de asemenea, dacă adăugați noi (sub)pachete.
Când aveți dubii, nu strică niciodată să reinstalați. Doar rulați din nou pip install -e ..

Requirements

Majoritatea proiectelor au unele dependențe. Cel mai probabil ați folosit
un fișier requirements.txt
înainte, sau un environment.yml
dacă folosiți conda. Acum că creați un setup.py, puteți specifica dependențele
în argumentul install_requires.
De exemplu, pentru un proiect tipic de știință a datelor puteți avea:

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

Puteți specifica cerințele fără versiune (PyYAML), fixați o versiune (pandas==0.23.3), specificați o versiune minimă
('numpy>=1.14.5) sau stabiliți un interval de versiuni (matplotlib>=2.2.0,<3.0.0). Aceste
cerințe vor fi instalate automat de către pip atunci când instalați pachetul dumneavoastră.

Extras-require

Câteodată este posibil să aveți dependențe care sunt necesare numai în anumite situații. În calitate de cercetător de date
Deseori fac pachete pe care le folosesc pentru a antrena un model. Când lucrez la un astfel de model în mod interactiv
este posibil să am nevoie să am instalate matplotlib și jupyter pentru a lucra interactiv cu datele
și pentru a crea vizualizări
ale performanței modelului. Pe de altă parte, dacă modelul rulează în producție, nu vreau
să instalez matplotlib și nici jupyter pe mașina (sau containerul) unde mă antrenez
sau fac inferența. Din fericire, setuptools permite specificarea dependențelor opționale în extras_require:

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

Acum, dacă instalăm pachetul în mod normal (pip install example din PyPI sau pip install -e . local)
se vor instala doar dependențele PyYAML, pandas și numpy. Cu toate acestea, atunci când specificăm
că dorim dependențele opționale interactive (pip install example
sau pip install -e .),
atunci vor fi instalate și matplotlib și jupyter.

Scripte și puncte de intrare

Cazul principal de utilizare al majorității pachetelor python pe care le instalați de la PyPI este acela de a furniza funcționalități
care pot fi utilizate în alt cod python. Cu alte cuvinte, puteți import din acele pachete.
În calitate de cercetător de date, deseori creez pachete care nu sunt menite să fie utilizate de alt cod python, dar
sunt menite să facă ceva, de exemplu să antreneze un model. Ca atare, am adesea un script python pe care
vreau să îl execut din linia de comandă.

Cel mai bun mod4 de a expune funcționalitatea pachetului dvs. la linia de comandă este să definiți
un entry_point astfel:

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

Acum puteți folosi comanda my-command din linia de comandă, care la rândul ei va executa main
funcția din interiorul exampleproject/example.py. Nu uitați să reinstalați – altfel comanda
nu va fi înregistrată.

Teste

Când scrieți orice cod, vă încurajez cu tărie să scrieți și teste pentru acest cod. Pentru testarea
cu python vă sugerez să folosiți pytest. Bineînțeles că nu doriți să adăugați pytest la dependențele
din install_requires: nu este necesar pentru utilizatorii pachetului dumneavoastră. Pentru ca acesta să fie instalat
automat atunci când rulați testele, puteți adăuga următoarele la setup.py:

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

În plus, va trebui să creați un fișier numit setup.cfg cu următorul conținut:

test=pytest

Acum puteți rula pur și simplu python setup.py test și setuptools se va asigura că dependențele necesare
sunt instalate și va rula pytest pentru dumneavoastră! Aruncați o privire aici dacă
doriți să furnizați argumente sau să setați opțiuni de configurare pentru pytest.

Dacă aveți cerințe suplimentare pentru testare (de exemplu pytest-flask) le puteți adăuga la tests_require.

Flake8

Personal cred că este o idee bună să rulați Flake8 pentru a
verifica formatarea codului dumneavoastră. La fel ca în cazul pytest, nu doriți să adăugați flake8 la dependențele
install_requires: nu este necesar să fie instalat pentru a utiliza pachetul dvs. În schimb, îl puteți adăuga la setup_requires:

setup( # ..., setup_requires=)

Acum puteți rula pur și simplu python setup.py flake8. Desigur, puteți, de asemenea, să fixați versiunea
de flake8 (sau orice alt pachet) în setup_requires.

Dacă doriți să modificați unii dintre parametrii de configurare ai Flake8, puteți adăuga o secțiune la
la setup.cfg dumneavoastră. De exemplu:

max-line-length=120

Date din pachet

Câteodată este posibil să doriți să includeți în pachetul dvs. unele fișiere non-python. Acestea
poate fi, de exemplu, fișiere de schemă sau un mic tabel de căutare. Fiți conștienți de faptul că astfel de fișiere
vor fi împachetate împreună cu codul dumneavoastră, așa că, în general, este o idee proastă să includeți
orice fișier de mari dimensiuni.

Să presupunem că avem un schema.json în proiectul nostru, pe care îl plasăm în exampleproject/data/schema.json.
Dacă vrem să-l includem în pachetul nostru, trebuie să folosim argumentul package_data din setup:

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

Aceasta se va asigura că fișierul este inclus în pachet. De asemenea, putem alege să includem
toate fișierele pe baza unui model, de exemplu:

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

Aceasta va adăuga toate fișierele *.json în orice pachet pe care îl întâlnește.

Acum nu încercați să vă dați seama singur de locația fișierelor instalate, deoarece
pkg_resources are câteva funcții de confort foarte utile:

  • pkg_resources.resource_stream vă va oferi un flux al fișierului, foarte asemănător cu obiectul
    pe care îl obțineți când apelați open(),
  • pkg_resources.resource_string vă va oferi conținutul fișierului sub forma unui șir de caractere,
  • pkg_resources.resource_filename vă va da numele fișierului (și îl va extrage
    într-un fișier temporar dacă este inclus într-un pachet zippat) pentru cazul în care cele două opțiuni
    de mai sus nu se potrivesc nevoilor dumneavoastră.

De exemplu, am putea citi în schema noastră folosind:

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

Metadate

Dacă aveți de gând să vă publicați pachetul, atunci probabil că doriți să le oferiți utilizatorilor
potențiali mai multe informații despre pachetul dumneavoastră, inclusiv o descriere,
numele autorului sau al celui care îl întreține și adresa URL a paginii de pornire a pachetului.
Puteți găsi o listă completă a tuturor metadatelor permise în setuptools
documente.

În plus, dacă aveți de gând să publicați în PyPI, atunci poate doriți să
încărcați automat conținutul README.md
în long_description,
și să furnizați clasificatori pentru a spune pip chiar
mai multe despre pachetul dumneavoastră.

Încheiere

Acest blog ar trebui să fie un bun punct de plecare pentru configurarea majorității proiectelor dvs. python.
Dacă doriți să citiți mai multe despre împachetarea python, aruncați o privire
la documentație. Iată un exemplu setup.py
care combină toate părțile prezentate în acest blog:

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

și setup.cfgcare însoțește setup.cfg:

test=pytestmax-line-length=120

Îmbunătățiți-vă abilitățile Python, învățați de la experți!

La GoDataDriven oferim o serie de cursuri Python de la începător la expert, predate de cei mai buni profesioniști în domeniu. Alăturați-vă nouă și îmbunătățiți-vă jocul Python:

  • Python Essentials – Excelent dacă sunteți la început cu Python.
  • Certified Data Science with Python Foundation – Vreți să faceți pasul de la analiza și vizualizarea datelor la adevărata știință a datelor? Acesta este cursul potrivit.
  • Advanced Data Science with Python – Învățați să vă produceți modelele ca un profesionist și să folosiți Python pentru machine learning.
Footnotes

0: În acest blog am folosit setuptools
pentru a configura proiectul meu de exemplu. Alternativ
ați putea folosi și distutils,
care este instrumentul standard pentru împachetarea în python, dar îi lipsesc caracteristici
cum ar fi funcția find_packages() și entry_points.
Din moment ce utilizarea lui setuptools este foarte comună în zilele noastre și multe dintre caracteristicile sale
pot fi deosebit de utile, vă sugerez să folosiți setuptools.

1: Dacă doriți ca versiunea pachetului dvs. să fie disponibilă și în interiorul python,
aruncați o privire aici.

2: Ați putea, de asemenea, să vă listați pachetele manual, dar acest lucru este deosebit de predispus la erori.

3: Alternativ, ați putea rula python setup.py install, dar utilizarea pip are
multe avantaje, printre care instalarea automată a dependențelor și posibilitatea
de a dezinstala sau actualiza pachetul dvs.

4: Ați putea, de asemenea, să folosiți argumentul scripts (a se vedea pentru
exemplu aici)
dar, deoarece acest lucru necesită crearea unui script shell python, este posibil să nu funcționeze
la fel de bine (sau deloc) pe Windows.

.

Lasă un răspuns

Adresa ta de email nu va fi publicată.