Pythons bekvemmelighed og alsidighed betyder, at det bruges til at bygge software i næsten alle dele af it-livet. En vigtig niche er webtjenester, hvor Pythons udviklingshastighed og fleksible metaforer gør det nemt at få hjemmesider hurtigt op at køre
Og ligesom du måske gætter det, giver Python dig masser af valgmuligheder og råderum i webframeworks, både små og store. Det er trods alt ikke alle webprojekter, der behøver at være i virksomhedsskala. De fleste bør være lige store nok til at få arbejdet gjort, og ikke større. Denne artikel gennemgår otte af de mest kendte Python-ramework, der lægger vægt på enkelhed, let levering og et stramt fokus.
Bottle
Bottle kan betragtes som en slags mini-Flask, da det er endnu mere kompakt og kortfattet end det andet “microframework”. På grund af sit minimale fodaftryk er Bottle ideel til at inkludere i andre projekter eller til hurtigt at levere små projekter som REST-API’er. (Flask er omtalt nedenfor.)
Hele kodebasen for Bottle passer i en enkelt fil og har absolut ingen eksterne afhængigheder. Alligevel er Bottle udstyret med nok funktionalitet til at bygge almindelige former for webapps uden at være afhængig af hjælp udefra.
Routing-systemet i Bottle, som mapper URL’er til funktioner, har næsten nøjagtig den samme syntaks som Flask. Du er heller ikke begrænset til et fast sæt af stier; du kan oprette dem dynamisk. Forespørgsels- og svardata, cookies, forespørgselsvariabler, formulardata fra en POST-handling, HTTP-headere og filopload kan alle tilgås og manipuleres ved hjælp af objekter i Bottle.
Alle muligheder er blevet implementeret med god opmærksomhed på detaljerne. Med filuploads behøver du f.eks. ikke at omdøbe filen, hvis dens navngivningskonvention er i konflikt med målfilsystemet (f.eks. skråstreger i navnet på Windows). Det kan Bottle gøre for dig.
Bottle indeholder sin egen enkle HTML-templating-motor. Igen, selv om den er minimal, har templating-motoren alle de væsentlige ting. Variabler, der indgår i en skabelon, gengives som standard med sikker HTML; du skal angive, hvilke variabler der er sikre at gengive bogstaveligt. Hvis du hellere vil udskifte Bottles skabelonmotor med en anden, f.eks. Jinja2, kan du gøre det uden besvær i Bottle. Jeg foretrækker det simple-skabelonsystem, der følger med Bottle; det er hurtigt, dets syntaks er uhøjtidelig, og det giver dig mulighed for at blande kode og skabelontekst uden unødige vanskeligheder.
Bottle understøtter endda flere serverbackends. Den leveres med sin egen indbyggede miniserver til hurtig testning, men vil også understøtte generisk WSGI, en lang række WSGI-kompatible HTTP-servere og almindelig gammel CGI, hvis det er nødvendigt.
Bottle har ikke brug for så meget dokumentation som andre frameworks, men dokumentationen er på ingen måde sparsom. Alt det afgørende stof passer på en enkelt (om end lang) webside. Ud over det finder du fuld dokumentation for hvert API, eksempler på udrulning på forskellige infrastrukturer, en forklaring på det indbyggede templating-sprog og en masse almindelige opskrifter.
Som med Flask kan du udvide Bottles funktionalitet manuelt eller via plug-ins. Bottle-plugins er langt fra så mange som Flasks, men der er nyttige dele, f.eks. integration med forskellige databaselag og grundlæggende brugergodkendelse. For asynkron understøttelse kan Bottle bruge en af de eksisterende serveradaptere, der kører asynkront, f.eks. aiohttp/uvloop, men async/await
understøttes ikke nativt.
En konsekvens af Bottles minimalisme er, at nogle elementer simpelthen ikke er der. Formularvalidering, herunder funktioner som CSRF-beskyttelse (cross-site request forgery), er ikke inkluderet. Hvis du ønsker at bygge et webprogram, der understøtter en høj grad af brugerinteraktion, skal du selv tilføje denne understøttelse.
Et andet problem med Bottle er, at udviklingen er gået i stå; den sidste punktudgivelse, 0.12, kom i 2013. Når det er sagt, bliver Bottle fortsat vedligeholdt, og dets udviklingsudgivelser kan fortsat bruges til produktion. Udviklerne har til hensigt at levere nye versioner, der mister understøttelsen af ældre udgaver af Python.
CherryPy
CherryPy har eksisteret i en eller anden form i næsten 20 år, men har ikke mistet den minimalisme og elegance, der kendetegnede den fra starten.
Målet med CherryPy er, ud over kun at indeholde de bare bits, der er nødvendige for at betjene websider, at det så vidt muligt ikke skal føles som en “webramme”, men som en hvilken som helst anden form for Python-applikation. Sider som Hulu og Netflix har brugt CherryPy i produktionen, fordi rammen giver en meget diskret base at bygge på. CherryPy bruger poolede tråde under motorhjelmen, så det er bedre til at understøtte multitrådede serveradaptere.
CherryPy lader dig holde din webapplikation adskilt fra kerne-logikken. For at mappe din applikations funktioner til URL’er eller ruter, der serveres af CherryPy, opretter du en klasse, hvor objektets namespaces mapper direkte til de URL’er, du ønsker at servere. F.eks. leveres webstedets rod af en funktion ved navn “index”. Parametre, der overføres til disse funktioner, bruges til at håndtere variabler, der leveres af GET- eller POST-metoder.
De bits, som CherryPy indeholder, er beregnet til at fungere som byggeklodser på lavt niveau. Sessionsidentifikatorer og cookiehåndtering er inkluderet, men HTML-templating er ikke inkluderet. Ligesom Bottle tilbyder CherryPy en måde at mappe ruter til mapper på disken til statisk filservering.
CherryPy vil ofte henvise til et eksisterende tredjepartsbibliotek for at understøtte en funktion i stedet for at levere den nativt. WebSocket-applikationer understøttes f.eks. ikke direkte af CherryPy, men gennem ws4py-biblioteket.
Dokumentationen til CherryPy indeholder en praktisk vejledning til gennemgang af de forskellige aspekter af programmet. Den tager dig ikke gennem en komplet end-to-end-applikation, i modsætning til nogle andre framework-tutorials, men den er stadig nyttig. Dokumentationen kommer med praktiske noter om implementering i virtuelle værter, reverse proxying via Apache og Nginx og mange andre scenarier.
Falcon
Hvis du bygger REST-baserede API’er og ikke andet, så er Falcon lavet lige til dig. Falcon er slank og hurtig og har næsten ingen afhængigheder ud over standardbiblioteket og indeholder alt, hvad du har brug for til REST-API’er og intet andet. Falcon 2.0, der blev udgivet i 2019, fjerner understøttelsen af Python 2.x og kræver mindst Python 3.5.
En stor del af grunden til, at Falcon fortjener betegnelsen “let og slank”, har ikke meget at gøre med antallet af kodelinjer i rammen. Det er fordi Falcon næsten ikke pålægger programmerne nogen egen struktur. Det eneste, som en Falcon-applikation skal gøre, er at angive, hvilke funktioner der mapper til hvilke API-endpoints. Returnering af JSON fra et endpoint indebærer ikke meget mere end at oprette en rute og returnere dataene via json.dumps
-funktionen fra Pythons standardbibliotek. Understøttelse af async er endnu ikke landet i Falcon, men der arbejdes på at få det til at ske i Falcon 3.0.
Falcon anvender også fornuftige out-of-the-box-defaults, så der er kun lidt fifleri nødvendigt for opsætningen. F.eks. bliver 404’er som standard udløst for enhver rute, der ikke er eksplicit erklæret. Hvis du ønsker at returnere fejl til klienten, kan du rejse en af en af de mange standard undtagelser, der følger med rammen (f.eks. HTTPBadRequest
), eller bruge en generisk falcon.HTTPError
undtagelse. Hvis du har brug for for- eller efterbehandling af en rute, tilbyder Falcon også hooks til disse.
Falcons fokus på API’er betyder, at der ikke er meget her til at bygge webapps med konventionelle HTML-brugergrænseflader. Du skal f.eks. ikke forvente meget i form af formularbehandlingsfunktioner og CSRF-beskyttelsesværktøjer. Når det er sagt, giver Falcon elegante muligheder for at udvide sin funktionalitet, så der kan bygges mere sofistikerede elementer. Ud over den ovennævnte hooking-mekanisme finder du en grænseflade til oprettelse af middleware, der kan bruges til at indpakke alle Falcons API’er.
Dokumentationen til Falcon er spinkel sammenlignet med andre frameworks, men kun fordi der er mindre at dække. Brugervejledningen indeholder en formel trin-for-trin-gennemgang af alle de vigtigste funktioner sammen med et quick-start-afsnit, hvor du kan se eksempler på kode med eller uden annotationer.
FastAPI
FastAPI’s navn er en god opsummering af, hvad den gør. Den er bygget til at oprette API-endpoints hurtigt, og den kører også hurtigt.
FastAPI gør brug af Starlette-projektet til sin højhastighedsnetværkskerne, men du behøver ikke at kende til Starlettes interne elementer for at bruge FastAPI. Du definerer endpoints på stort set samme måde som en Flask- eller Bottle-app – brug dekoratorer til at angive, hvilke funktioner der håndterer hvilke ruter – og returnerer derefter ordbøger, der automatisk oversættes til JSON.
Du kan nemt overstyre, hvordan tingene returneres. Hvis du f.eks. ønsker at returnere HTML/XML fra nogle endpoints, kan du gøre det ved blot at returnere et brugerdefineret Response
objekt. Hvis du ønsker at tilføje brugerdefineret middleware, kan du indsætte alt, der følger ASGI-standarden.
FastAPI gør brug af Pythons type hinting for at give begrænsninger på de typer af data, som ruterne accepterer. Hvis du f.eks. har en rute med typen Optional
, vil FastAPI afvise alle indsendelser undtagen hele tal. Du behøver ikke at tilføje datavalideringskode til dine endpoints; du kan bare bruge typehints og lade FastAPI gøre arbejdet.
Naturligvis er der nogle ting, der udelades. Der er f.eks. ingen indbygget HTML-skabelonmotor, men der er ingen mangel på løsninger fra tredjeparter til at udfylde dette hul. Det samme med databaseforbindelse, men dokumentationen indeholder detaljer om, hvordan man kan overtale visse ORM’er (f.eks. Peewee) til at arbejde med FastAPI’s asynkrone adfærd.
Flask
Mange diskussioner om Python-webrameworks begynder med Flask, og det er der en god grund til. Flask er en veletableret, velforstået ramme, der er nem at bruge og ret stabil. Det er næsten umuligt at gå galt i byen ved at bruge Flask til et letvægtswebprojekt eller et grundlæggende REST API, men du vil stå over for tunge løft, hvis du forsøger at bygge noget større.
Flasks centrale appel er dens lave adgangsbarriere. En grundlæggende “hello world”-app kan oprettes på mindre end 10 linjer Python. Flask indeholder et udbredt HTML-templating-system, Jinja2, for at gøre det nemt at rendere tekst, men Jinja2 kan udskiftes med et hvilket som helst antal andre template-motorer (såsom Mustache), eller du kan lave din egen.
I enkelhedens navn udelader Flask finurligheder såsom et datalag eller ORM og tilbyder ingen bestemmelser for formularvalidering. Flask kan dog udvides gennem udvidelser, som der er dusinvis af, og som dækker mange almindelige anvendelsestilfælde såsom caching, formularhåndtering og validering samt databasetilslutning. Dette lean-by-default-design giver dig mulighed for at starte med at udvikle en Flask-applikation med det absolutte minimum af funktionalitet og derefter kun lægge de dele ind, du har brug for, når du har brug for dem.
Flasks dokumentation er genial og letlæselig. Quick-start-dokumentet gør et fremragende stykke arbejde med at få dig i gang, samtidig med at det forklarer betydningen af standardvalg for en simpel Flask-applikation, og API-dokumentationen er fyldt med gode eksempler. Fremragende er også samlingen af Flask-snippets, som er hurtige eksempler på, hvordan man udfører specifikke opgaver, f.eks. hvordan man returnerer et objekt, hvis det eksisterer, eller en 404-fejl, hvis det ikke gør.
Flask nåede sin milepæl 1.0-udgivelse i 2018, hvor Python 2.6 og Python 3.3 er de mindst understøttede versioner, og hvor mange af dens adfærd endelig ligger i sten. Flask understøtter ikke eksplicit Pythons asynkrone syntaks, men en API-kompatibel variant af Flask kaldet Quart er blevet spunset ud for at opfylde dette krav.
Pyramid
Pyramid er lille og let og egner sig godt til opgaver som f.eks. at eksponere eksisterende Python-kode som et REST API eller at levere kernen i et webprojekt, hvor udvikleren gør det meste af det tunge arbejde.
“Pyramid giver dig mulighed for at blive produktiv hurtigt og vil vokse med dig,” står der i dokumentationen. “Den vil ikke holde dig tilbage, når din applikation er lille, og den vil ikke stå i vejen for dig, når din applikation bliver stor.”
En god måde at beskrive Pyramids minimalisme på ville være “fri for politik”, et udtryk, der bruges i det afsnit i dokumentationen, der diskuterer, hvordan Pyramid klarer sig i forhold til andre webframeworks. Dybest set betyder “fri for politik”, at hvilken database eller hvilket templating-sprog du vælger at bruge, er ikke Pyramids bekymring.
Det kræver meget lidt arbejde at opbygge en grundlæggende Pyramid-applikation. Ligesom med Bottle og Flask kan en Pyramid-applikation bestå af en enkelt Python-fil, bortset fra filerne til selve rammen. Et simpelt API med en enkelt rute kræver ikke mere end en snes linjer kode eller deromkring. Det meste af det er boilerplate som from … import
-angivelser og opsætning af WSGI-serveren.
Som standard indeholder Pyramid flere elementer, der er almindelige i webapplikationer, men de leveres som komponenter, der skal sættes sammen, ikke som fuldgyldige løsninger. Understøttelse af brugersessioner, for eksempel, leveres endda med CSRF-beskyttelse. Men understøttelse af brugerkonti, som f.eks. logins eller kontoadministration, er ikke en del af aftalen. Du er nødt til selv at rulle det eller tilføje det via et plug-in. Det samme gælder for formularhåndtering og databaseforbindelser.
Pyramid tilbyder endda en måde at oprette skabeloner fra tidligere Pyramid-projekter for at genbruge tidligere arbejde. Disse skabeloner, kaldet “scaffolds”, genererer en Pyramid-app med simpel routing og nogle start HTML/CSS-skabeloner. De medfølgende scaffolds omfatter et eksempel på et startprojekt og et projekt, der opretter forbindelse til databaser via det populære Python-bibliotek SQLAlchemy.
Pyramids slanke test- og fejlfindingsværktøjer klarer opgaven. Pak debugtoolbar
-udvidelsen ind i en Pyramid-app, og du får et klikbart ikon på hver webside, der genererer detaljer om appens udførelse, herunder en detaljeret sporing i tilfælde af fejl. Logning og enhedstest er også til stede.
Pyramids dokumentation er fremragende. Ud over en hurtig rundvisning af det grundlæggende og en gennemgang i stil med en tutorial finder du et sæt tutorials, der er bidraget af fællesskabet, og en kogebog med almindelige opskrifter. Sidstnævnte indeholder implementeringsteknikker til en lang række målmiljøer, fra Google App Engine til Nginx.
Pyramid understøtter både Python 2 og Python 3, men bruger ikke Python 3’s asynkrone syntaks. Hvis du ønsker at udnytte async i Pyramid, kan du se aiopyramid-projektet, som indeholder et stillads til en async-drevet “hello world”-applikation.
Sanic
Sanic er designet med henblik på hastighed og enkelhed og fungerer med Python 3.6 eller højere og bruger Pythons async/await
-syntaks (tilgængelig fra Python 3.5), så du kan oprette effektive webapplikationer.
Som med Flask eller Bottle kører en grundlæggende Sanic-“hello world” ca. 10 linjer kode, hvoraf det meste er import og anden boilerplate. Den vigtigste forskel er, at applikationsruter skal deklareres som async def
-funktioner, og du skal bruge await
til at kalde disse funktioner i din asynkron kode. Hvis du har skrevet async-drevne programmer før, har du allerede den sværeste del i bagagen.
Mange af de mekanismer, som Sanic bruger til at håndtere forbindelser og svar, vil være velkendte. Anmodninger og svar er blot objekter med velkendte egenskaber, som uploadede filer, formularer, JSON-objekter, overskrifter osv.
Applikationer med mange ruter bliver uoverskuelige at administrere. Sanic løser dette problem med “blueprints”, objekter, der kan beskrive grupper af ruter og give dig mulighed for at administrere dem via en grænseflade på højt niveau. I stedet for at skrive hver enkelt rute eksplicit eller bruge et overskud af ruter med variabler kan du skrive et par blueprints til generisk at beskrive, hvordan ruterne fungerer i din app (f.eks. /object/object_id/action
). Blueprints kan have fælles middleware, hvilket er nyttigt, hvis du ønsker at anvende forvaltningsfunktionalitet på nogle ruter, men ikke på andre.
Sanic fungerer også med andre protokoller end HTTP. WebSocket-endpoints kræver kun en anden decorator og lidt mere intern logik (f.eks. afventning og håndtering af svar). Brugerdefinerede netværksprotokoller kan understøttes ved at underklasser asyncio.protocol
.
Sanic udelader bevidst funktionalitet som databasetilslutning og HTML-templating, mens den beholder de funktioner, man ville bruge til at tilslutte disse funktioner: middleware, centraliseret programkonfiguration osv.
Tornado
Tornado er en anden lille ramme, der er rettet mod et specifikt anvendelsestilfælde: asynkrone netværksapplikationer. Tornado er velegnet til at skabe tjenester, der åbner mange netværksforbindelser og holder dem i live – det vil sige alt, der involverer WebSockets eller lange afstemninger. Tornado 6.0 kræver Python 3.5 eller højere, og dropper helt understøttelsen af Python 2.
Lige Bottle eller Falcon udelader Tornado funktioner, der er uden betydning for det centrale formål. Tornado har et indbygget templating-system til generering af HTML og andet output og indeholder mekanismer til internationalisering, formularhåndtering, cookie-indstilling, brugergodkendelse og CSRF-beskyttelse. Men den udelader funktioner som formularvalidering og en ORM, der primært er beregnet til brugervendte webapplikationer.
Tornado udmærker sig ved at levere infrastruktur til applikationer, der har brug for tæt kontrol over asynkrone netværk. Tornado tilbyder f.eks. ikke kun en indbygget asynkron HTTP-server, men også en asynkron HTTP-klient. Tornado er således velegnet til at bygge apps, f.eks. en webscraper eller en bot, der forespørger andre websteder parallelt og handler på de returnerede data.
Hvis du ønsker at oprette en app, der bruger andre protokoller end HTTP, er du dækket ind af Tornado. Tornado giver adgang til TCP-forbindelser og sockets på lavt niveau til hjælpeprogrammer som DNS-resolvere samt til autentificeringstjenester fra tredjeparter, og den understøtter samarbejde med andre frameworks via WSGI-standarden. Dokumentationen, som er lille, men ikke sparsom, indeholder rigeligt med eksempler til at opnå alt dette.
Tornado både udnytter og supplerer Pythons native funktionalitet til asynkron adfærd. Hvis du bruger Python 3.5, understøtter Tornado de indbyggede nøgleord async
og await
, som lover at give programmerne et hastighedsboost. Du kan også bruge futures eller callbacks til at håndtere svar på hændelser.
Tornado indeholder et bibliotek af synkroniseringspræmier – semahores, locks osv. – til at koordinere hændelser mellem asynkrone coroutiner. Bemærk, at Tornado normalt kører single-threaded, så disse primitiver er ikke det samme som deres navnebrødre til threading. Hvis du imidlertid ønsker at køre Tornado i parallelle processer for at udnytte flere sockets og kerner, er der værktøjer til rådighed til at gøre det.
Tornados dokumentation dækker hvert større koncept i rammen og alle de vigtigste API’er i modellen. Selv om den indeholder en prøveapplikation (en webcrawler), er den primært beregnet til at demonstrere Tornados kømodul.