Data & AI-utbildningsguide 2021
Ladda ner GoDataDriven-broschyren för att få en fullständig översikt över tillgängliga utbildningssessioner och lärandebesök inom datateknik, datavetenskap, dataanalytik och analysöversättning.
När du använder python professionellt lönar det sig att sätta upp dina projekt
på ett konsekvent sätt. Detta hjälper dina medarbetare att snabbt förstå
strukturen i ett projekt och gör det lättare för dem att konfigurera projektet
på sin maskin. Nyckeln till att ställa in ditt projekt är setup.py
-filen.
I den här bloggen kommer jag att gå in på detaljerna i den här filen.
Hur vi börjar
Här utgår jag från att du redan har ett paket som du vill ställa in.
Det här behöver inte vara ett färdigt paket – idealt sett bör du skapasetup.py
långt innan ditt projekt är färdigt. Det kan till och med vara ett tomt paket;
säkerställ bara att paketmappen finns
och innehåller en fil som heter init.py
(som kan vara tom).
Om du följer min kollega Henks struktur
för ditt projekt bör din utgångssituation se ut ungefär så här:
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.
Du kan ha andra filer eller mappar i din struktur, till exempel
mappar som heter notebooks/
, tests/
eller data/
, men dessa är inte nödvändiga.
Fallet för en setup.py
När du har skapat ett paket som detta är det troligt
att du kommer att använda en del av koden på andra ställen. Du kanske till exempel vill
göra detta i en anteckningsbok:
from exampleproject.example import example_function
Detta skulle fungera om din nuvarande arbetskatalog är example_project/
, men i
alla andra fall kommer python att ge dig utdata som:
ModuleNotFoundError: No module named 'exampleproject'
Du skulle kunna tala om för python var paketet ska sökas genom att ställa in PYTHONPATH
miljövariabeln eller lägga till sökvägen i sys.path
,
men det är långt ifrån idealiskt: det skulle kräva olika åtgärder på olika plattformar, och sökvägen du behöver ställa in beror på var koden finns.
Ett mycket bättre sätt är att installera ditt paket med hjälp av en setup.py
och pip
,
eftersom pip
är standardsättet att installera alla andra paket, och det är bundet
att fungera likadant på alla plattformar.
Ett minimalt exempel
Så hur ser en setup.py
fil ut? Här är ett minimalt exempel0:
from setuptools import setup, find_packagessetup( name='example', version='0.1.0', packages=find_packages(include=))
Här specificerar vi tre saker:
- Namnet på paketet, vilket är det namn som
pip
kommer att använda för ditt paket.
Detta behöver inte vara detsamma som namnet på mappen som paketet bor
i, även om det kan vara förvirrande om det inte är det. Ett exempel där paket
namnet och mappen inte stämmer överens är Scikit-Learn: du installerar det
med hjälp avpip install scikit-learn
, medan du använder det genom att importera frånsklearn
. - Versionen av ditt paket. Detta är den version som
pip
kommer att rapportera, och används
till exempel när du publicerar ditt paket på PyPI1. - Vilka paket som ska inkluderas; i vårt fall är detta bara
exampleproject/
.
Här låter visetuptools
räkna ut detta
automatiskt2. Även om du i princip skulle kunna användafind_packages()
utan några argument kan detta potentiellt leda till att oönskade paket
inkluderas. Detta kan till exempel hända
om du inkluderade en__init__.py
i dintests/
katalog. Alternativt kan du också användaexclude
-argumentet för att uttryckligen
förhindra att tester inkluderas i paketet, men detta är något
mindre robust.
Nu är allt du behöver göra för att installera ditt paket att köra följande
från insidan av example_project/
katalogen3:
pip install -e .
Den .
här hänvisar till den aktuella arbetskatalogen, vilket jag antar är den katalog
där setup.py
kan hittas. Flaggan -e
anger att vi vill installera
i redigerbart läge, vilket innebär
att när vi redigerar filerna i vårt paket behöver vi inte installera om
paketet innan ändringarna träder i kraft. Du måste dock antingen starta om
python eller ladda om paketet!
När du redigerar information i själva setup.py
behöver du i de flesta fall installera om
paketet, och även om du lägger till nya (under)paket.
När du är osäker kan det aldrig skada att installera om. Det är bara att köra pip install -e .
igen.
Krav
De flesta projekt har vissa beroenden. Du har troligen använt
en requirements.txt
fil tidigare, eller en environment.yml
om du använder conda
. Nu när du skapar en setup.py
kan du ange dina
beroenden i install_requires
-argumentet.
För ett typiskt datavetenskapsprojekt kan du till exempel ha:
setup( name='example', version='0.1.0', packages=find_packages(include=), install_requires=)
Du kan ange krav utan version (PyYAML
), ange en version (pandas==0.23.3
), ange en minsta
version ('numpy>=1.14.5
) eller ställa in ett intervall av versioner (matplotlib>=2.2.0,<3.0.0
). Dessa
krav installeras automatiskt av pip
när du installerar ditt paket.
Extras-require
Ibland kan du ha beroenden som endast krävs i vissa situationer. Som datavetare
gör jag ofta paket som jag använder för att träna en modell. När jag arbetar interaktivt
med en sådan modell kan jag behöva ha matplotlib
och jupyter
installerade för att interaktivt kunna arbeta med
data och skapa visualiseringar
av modellens prestanda. Å andra sidan, om modellen körs i produktion vill jag inte
installera matplotlib
eller jupyter
på den maskin (eller container) där jag tränar
eller gör inferenser. Som tur är gör setuptools
det möjligt att ange valfria beroenden i extras_require
:
setup( name='example', version='0.1.0', packages=find_packages(include=), install_requires=, extras_require={ 'interactive': , })
Om vi nu installerar paketet normalt (pip install example
från PyPI eller pip install -e .
lokalt)
installerar det bara beroendena PyYAML
, pandas
och numpy
. Men när vi anger
att vi vill ha de valfria interactive
beroendena (pip install example
eller pip install -e .
),
då kommer matplotlib
och jupyter
också att installeras.
Skripter och ingångspunkter
Det huvudsakliga användningsfallet för de flesta python-paket som du installerar från PyPI är att tillhandahålla funktionalitet
som kan användas i annan pythonkod. Med andra ord kan duimport
från dessa paket.
Som datavetare gör jag ofta paket som inte är tänkta att användas av annan pythonkod men
är tänkta att göra något, till exempel att träna en modell. Som sådan har jag ofta ett pythonskript som
jag vill exekvera från kommandoraden.
Det bästa sättet4 att exponera funktionaliteten i ditt paket för kommandoraden är att definiera
en entry_point
på följande sätt:
setup( # ..., entry_points={ 'console_scripts': })
Nu kan du använda kommandot my-command
från kommandoraden, vilket i sin tur kommer att exekvera main
funktionen inuti exampleproject/example.py
. Glöm inte att installera om – annars registreras inte kommandot
.
Tester
När du skriver någon kod uppmanar jag dig starkt att också skriva tester för denna kod. För testning
med python föreslår jag att du använder pytest
. Naturligtvis vill du inte lägga till pytest
till dina beroenden
i install_requires
: det krävs inte av användarna av ditt paket. För att den ska installeras
automatiskt när du kör tester kan du lägga till följande i din setup.py
:
setup( # ..., setup_requires=, tests_require=,)
Du måste dessutom skapa en fil som heter setup.cfg
med följande innehåll:
test=pytest
Nu kan du helt enkelt köra python setup.py test
och setuptools
kommer att se till att de nödvändiga beroendena
installeras och köra pytest
åt dig! Ta en titt här om
du vill ge argument eller ställa in konfigurationsalternativ för pytest
.
Om du har ytterligare krav för testning (t.ex. pytest-flask
) kan du lägga till dem i tests_require
.
Flake8
Personligen tycker jag att det är en bra idé att köra Flake8 för att
kontrollera formateringen av din kod. Precis som med pytest
vill du inte lägga till flake8
i beroendenainstall_requires
: det behöver inte installeras för att du ska kunna använda ditt
paket. Istället kan du lägga till den i setup_requires
:
setup( # ..., setup_requires=)
Nu kan du helt enkelt köra python setup.py flake8
. Naturligtvis kan du också fästa versionen
av flake8
(eller något annat paket) i setup_requires
.
Om du vill ändra några av konfigurationsparametrarna för Flake8 kan du lägga till en sektion till
ditt setup.cfg
. Till exempel:
max-line-length=120
Paketdata
Ibland vill du kanske inkludera några icke-pythonfiler i ditt paket. Dessa
kan till exempel vara schemafiler eller en liten uppslagstabell. Var medveten om att sådana filer
kommer att paketeras tillsammans med din kod, så det är i allmänhet en dålig idé att inkludera
någon stor fil.
Antag att vi har en schema.json
i vårt projekt, som vi placerar i exampleproject/data/schema.json
.
Om vi vill inkludera den i vårt paket måste vi använda package_data
argumentet i setup
:
setup( # ..., package_data={'exampleproject': })
Detta ser till att filen inkluderas i paketet. Vi kan också välja att inkludera
alla filer baserat på ett mönster, till exempel:
setup( # ..., package_data={'': })
Detta kommer att lägga till alla *.json
filer i alla paket den möter.
Va inte försöka räkna ut de installerade filernas placering själv, eftersompkg_resources
har några mycket praktiska bekvämlighetsfunktioner:
-
pkg_resources.resource_stream
ger dig en ström av filen, ungefär som
objektet du får när du anroparopen()
, -
pkg_resources.resource_string
ger dig innehållet i filen som en sträng, -
pkg_resources.resource_filename
ger dig filnamnet på filen (och extraherar
den till en temporär om den ingår i ett komprimerat paket) för om de två alternativen
ovan inte passar dina behov.
Till exempel kan vi läsa in vårt schema med hjälp av:
from json import loadfrom pkg_resources import resource_streamschema = load(resource_stream('exampleproject', 'data/schema.json'))
Metadata
Om du ska publicera ditt paket vill du antagligen ge dina
potentiella användare lite mer information om paketet, bland annat en beskrivning,
namnet på författaren eller den som ansvarar för paketet, och webbadressen till paketets hemsida.
En fullständig lista över alla tillåtna metadata finns i setuptools
docs.
Om du ska publicera till PyPI kanske du dessutom vill
automatiskt ladda in innehållet i ditt README.md
i long_description
,
och tillhandahålla klassificerare för att berätta pip
ännu
mer om ditt paket.
Uppackning
Den här bloggen bör vara en bra utgångspunkt för att ställa in de flesta av dina pythonprojekt.
Om du vill läsa mer om python-paketering kan du ta en titt
på dokumentationen. Här är ett exempel setup.py
som kombinerar alla delar som visas i den här bloggen:
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': })
och den medföljande setup.cfg
:
test=pytestmax-line-length=120
Förbättra dina Pythonkunskaper, lär dig av experterna!
På GoDataDriven erbjuder vi en mängd Pythonkurser från nybörjare till expert, som lärs ut av de bästa proffsen inom området. Följ med oss och höj nivån på dina Pythonkunskaper:
- Python Essentials – Perfekt om du precis har börjat med Python.
- Certified Data Science with Python Foundation – Vill du ta steget från dataanalys och visualisering till riktig datavetenskap? Det här är rätt kurs.
- Advanced Data Science with Python – Lär dig producera dina modeller som ett proffs och använd Python för maskininlärning.
Fotnoter
0: I den här bloggen har jag använt setuptools
för att ställa in mitt exempelprojekt. Alternativt
kan du också använda distutils,
som är standardverktyget för paketering i python, men det saknar funktioner
som find_packages()
funktionen och entry_points
.
Då användningen av setuptools är mycket vanlig nuförtiden och många av dess funktioner
kan vara särskilt användbara, föreslår jag att du ska använda setuptools.
1: Om du vill att versionen av ditt paket också ska finnas tillgänglig inuti python,
ha en titt här.
2: Du skulle också kunna lista dina paket manuellt, men detta är särskilt felbenäget.
3: Alternativt skulle du kunna köra python setup.py install
, men att använda pip
har
många fördelar, bland annat automatisk installation av beroenden och
möjligheten att avinstallera eller uppdatera ditt paket.
4: Du skulle också kunna använda scripts
argumentet (se för
exempel här)
men eftersom detta kräver att du skapar ett python-skalskript kanske det inte fungerar
lika bra (eller inte alls) på Windows.