Pythons bekvämlighet och mångsidighet gör att det används för att bygga mjukvara i nästan alla delar av IT-livet. En viktig nisch är webbtjänster, där Pythons utvecklingshastighet och flexibla metaforer gör det lätt att snabbt få igång webbplatser.
Och precis som du kanske kan gissa ger Python dig massor av valmöjligheter och handlingsutrymme när det gäller webbramverk, både små och stora. Det är trots allt inte alla webbprojekt som behöver vara av företagsstorlek. De flesta bör vara precis tillräckligt stora för att få jobbet gjort, och inte större. I den här artikeln kartläggs åtta av de mest kända Pythonramverken som betonar enkelhet, lättviktiga leveranser och ett snävt fokus.
Bottle
Bottle kan betraktas som ett slags mini-Flask, eftersom det är ännu mer kompakt och kortfattat än det andra ”mikroramverket”. På grund av sitt minimala fotavtryck är Bottle idealisk för att inkluderas i andra projekt eller för att snabbt leverera små projekt som REST API:er. (Flask diskuteras nedan.)
Hela kodbasen för Bottle ryms i en enda fil och har absolut inga externa beroenden. Trots detta är Bottle utrustad med tillräckligt med funktionalitet för att bygga vanliga typer av webbapplikationer utan att förlita sig på hjälp utifrån.
Routing-systemet i Bottle, som mappar URL:er till funktioner, har nästan exakt samma syntax som Flask. Du är inte heller begränsad till en fast uppsättning sökvägar; du kan skapa dem dynamiskt. Förfrågnings- och svarsdata, cookies, frågevariabler, formulärdata från en POST-åtgärd, HTTP-huvuden och filuppladdningar kan alla nås och manipuleras med hjälp av objekt i Bottle.
Varje funktion har implementerats med god omsorg om detaljerna. Med filuppladdningar behöver du till exempel inte byta namn på filen om dess namnkonvention krockar med målfilsystemet (t.ex. snedstreck i namnet i Windows). Bottle kan göra det åt dig.
Bottle innehåller sin egen enkla HTML-templatingmotor. Även om den är minimal har den allt det nödvändigaste. Variabler som ingår i en mall återges som standard med säker HTML; du måste ange vilka variabler som är säkra att återge bokstavligen. Om du hellre vill byta ut Bottles mallmotor mot en annan, till exempel Jinja2, låter Bottle dig göra det utan krångel. Jag föredrar det enkla mallsystem som levereras med Bottle; det är snabbt, syntaxen är opretentiös och du kan blanda kod och malltext utan onödiga svårigheter.
Bottle har till och med stöd för flera serverbackends. Den levereras med sin egen inbyggda miniserver för snabb testning, men stöder också generisk WSGI, ett stort antal WSGI-kompatibla HTTP-servrar och vanlig gammal CGI om det behövs.
Bottle behöver inte lika mycket dokumentation som andra ramverk, men dokumentationen är på intet sätt sparsam. Allt det viktiga ryms på en enda (om än lång) webbsida. Utöver det hittar du fullständig dokumentation för varje API, exempel på hur man distribuerar på olika infrastrukturer, en förklaring av det inbyggda mallspråket och en mängd vanliga recept.
Som med Flask kan du utöka Bottles funktionalitet manuellt eller via plugins. Flask-plugins är inte alls lika många som Flasks, men det finns användbara delar, t.ex. integration med olika databaslager och grundläggande användarautentisering. För asynkront stöd kan Bottle använda en av de befintliga serveradaptrarna som körs asynkront, t.ex. aiohttp/uvloop, men async/await
har inte nativt stöd.
En konsekvens av Bottles minimalism är att vissa saker helt enkelt inte finns där. Formulärvalidering, inklusive funktioner som CSRF-skydd (cross-site request forgery), ingår inte. Om du vill bygga en webbapplikation som stöder en hög grad av användarinteraktion måste du lägga till det stödet själv.
Ett annat problem med Bottle är att utvecklingen har avstannat; den senaste punktutgåvan, 0.12, kom 2013. Bottle fortsätter dock att underhållas och dess utvecklingsversioner är fortfarande användbara för produktion. Utvecklarna har för avsikt att leverera nya versioner som avstår från stöd för äldre utgåvor av Python.
CherryPy
CherryPy har funnits i en eller annan form i nästan 20 år, men har inte förlorat den minimalism och elegans som utmärkte den från början.
Målet med CherryPy, förutom att det bara innehåller de nakna bitar som behövs för att betjäna webbsidor, är att så långt det är möjligt inte kännas som ett ”ramverk för webben” utan som vilken annan typ av Pythonprogram som helst. Webbplatser som Hulu och Netflix har använt CherryPy i produktionen eftersom ramverket ger en mycket diskret bas att bygga på. CherryPy använder poolade trådar under huven, för att bättre kunna stödja serveradaptrar med flera trådar.
CherryPy låter dig hålla din webbapplikation åtskild från kärnlogiken. För att mappa applikationens funktioner till webbadresser eller rutter som serveras av CherryPy skapar du en klass där objektens namnområden mappas direkt till de webbadresser som du vill servera. Webbplatsens rot tillhandahålls till exempel av en funktion som heter ”index”. Parametrar som skickas till dessa funktioner används för att hantera variabler som tillhandahålls av GET- eller POST-metoder.
De bitar som CherryPy innehåller är avsedda att fungera som byggblock på låg nivå. Sessionsidentifierare och cookiehantering ingår, men HTML-templering ingår inte. Liksom Bottle erbjuder CherryPy ett sätt att mappa rutter till kataloger på disken för statisk filservering.
CherryPy kommer ofta att hänvisa till ett befintligt bibliotek från tredje part för att stödja en funktion i stället för att tillhandahålla den nativt. WebSocket-applikationer stöds till exempel inte direkt av CherryPy, utan genom biblioteket ws4py.
Dokumentationen för CherryPy innehåller en praktisk handledning som går igenom de olika aspekterna av programmet. Den tar dig inte igenom en komplett tillämpning från början till slut, till skillnad från vissa andra ramverkshandledningar, men den är ändå användbar. Dokumentationen innehåller praktiska anteckningar om distribution i virtuella värdar, reverse proxying via Apache och Nginx och många andra scenarier.
Falcon
Om du bygger REST-baserade API:er och inget annat så är Falcon gjort just för dig. Falcon är smidig och snabb, med nästan inga beroenden utöver standardbiblioteket, och erbjuder allt du behöver för REST-API:er och inget annat. Falcon 2.0, som släpptes 2019, tar bort stödet för Python 2.x och kräver minst Python 3.5.
En stor del av anledningen till att Falcon förtjänar etiketten ”lätt och slank” har inte så mycket att göra med antalet rader kod i ramverket. Det beror på att Falcon nästan inte påtvingar programmen någon egen struktur. Allt en Falcon-applikation behöver göra är att ange vilka funktioner som mappas till vilka API-slutpunkter. Att returnera JSON från en slutpunkt innebär inte mycket mer än att ställa in en rutt och returnera data via funktionen json.dumps
från Pythons standardbibliotek. Stöd för async har ännu inte landat i Falcon, men arbete pågår för att göra det möjligt i Falcon 3.0.
Falcon använder sig också av sunda out-of-the-box-standardinställningar, så det behövs lite pyssel för inställningen. Till exempel, 404:s tas upp som standard för alla rutter som inte uttryckligen deklareras. Om du vill returnera fel till klienten kan du ta upp ett av ett antal standardutmärkelser som ingår i ramverket (t.ex. HTTPBadRequest
) eller använda ett generiskt falcon.HTTPError
-utmärkelse. Om du behöver för- eller efterbearbetning för en rutt tillhandahåller Falcon krokar för dessa också.
Falcons fokus på API:er innebär att det finns lite här för att bygga webbapplikationer med konventionella HTML-användargränssnitt. Förvänta dig inte mycket i form av formulärbehandlingsfunktioner och CSRF-skyddsverktyg, till exempel. Med det sagt ger Falcon eleganta alternativ för att utöka sin funktionalitet, så att mer sofistikerade objekt kan byggas. Förutom den ovan nämnda hooking-mekanismen hittar du ett gränssnitt för att skapa middleware som kan användas för att omsluta alla Falkons API:er.
Dokumentationen för Falcon är smal jämfört med andra ramverk, men bara för att det finns mindre att täcka in. Användarhandboken innehåller en formell steg-för-steg genomgång av alla viktiga funktioner, tillsammans med ett avsnitt för snabbstart där du kan se exempelkod med eller utan annotationer.
FastAPI
FastAPI:s namn är en bra sammanfattning av vad den gör. Den är byggd för att skapa API-slutpunkter snabbt, och den körs också snabbt.
FastAPI använder sig av Starlette-projektet för sin höghastighetsnätverkskärna, men du behöver inte känna till Starlettes interna delar för att använda FastAPI. Du definierar slutpunkter på ungefär samma sätt som en Flask- eller Bottle-app – använd dekoratorer för att ange vilka funktioner som hanterar vilka rutter och returnera sedan ordlistor som översätts automatiskt till JSON.
Du kan enkelt åsidosätta hur saker returneras. Om du till exempel vill returnera HTML/XML från vissa slutpunkter kan du göra det genom att helt enkelt returnera ett anpassat Response
objekt. Om du vill lägga till anpassad middleware kan du lägga in vad som helst som följer ASGI-standarden.
FastAPI använder sig av Pythons type hinting för att ge begränsningar för vilka typer av data som vägarna accepterar. Om du till exempel har en rutt med typen Optional
kommer FastAPI att avvisa alla inlämningar utom heltal. Du behöver inte lägga till kod för datavalidering i dina ändpunkter; du kan bara använda type hints och låta FastAPI göra jobbet.
Naturligtvis lämnas vissa saker bort. Det finns till exempel ingen inbyggd HTML-mallmotor, men det råder ingen brist på tredjepartslösningar för att fylla den luckan. Samma sak med databasanslutning, men dokumentationen innehåller detaljer om hur man övertalar vissa ORM:er (t.ex. Peewee) att arbeta med FastAPI:s asynkrona beteenden.
Flask
Många diskussioner om Python-webbramverk börjar med Flask, och det på goda grunder. Flask är ett väletablerat, välförstått ramverk som är lätt att använda och ganska stabilt. Det är näst intill omöjligt att göra fel när man använder Flask för ett lättviktigt webbprojekt eller ett grundläggande REST-API, men det blir tungt om man försöker bygga något större.
Flasks centrala dragningskraft är dess låga inträdesbarriär. En grundläggande ”hello world”-applikation kan skapas på mindre än 10 rader i Python. Flask innehåller ett allmänt använt HTML-templatsystem, Jinja2, för att göra det enkelt att rendera text, men Jinja2 kan bytas ut mot ett antal andra mallmotorer (t.ex. Mustache) eller så kan du skapa en egen.
I enkelhetens namn utelämnar Flask finesser som ett datalager eller ORM, och erbjuder inga bestämmelser för t.ex. validering av formulär. Flask kan dock utökas med hjälp av tillägg, som det finns dussintals av, och som täcker många vanliga användningsområden som cachelagring, formulärhantering och validering samt databasanslutning. Denna lean-by-default-design gör att du kan börja konstruera en Flask-applikation med ett absolut minimum av funktionalitet och sedan lägga in endast de delar du behöver när du behöver dem.
Flasks dokumentation är genial och lättläst. Snabbstartdokumentet gör ett utmärkt jobb med att få igång dig samtidigt som det förklarar betydelsen av standardvalen för en enkel Flask-applikation, och API-dokumentationen är fylld av bra exempel. Utmärkt är också samlingen av Flask-snippets, som är snabba och smutsiga exempel på hur man utför specifika uppgifter, t.ex. hur man returnerar ett objekt om det finns eller ett 404-fel om det inte finns.
Flask nådde sin milstolpe 1.0-utgåva 2018, med Python 2.6 och Python 3.3 som minsta stödda versioner, och med många av dess beteenden äntligen fastslagna i sten. Flask stöder inte uttryckligen Pythons asynkrona syntax, men en API-kompatibel variant av Flask kallad Quart har avknoppats för att tillgodose den efterfrågan.
Pyramid
Pyramid är liten och lätt och lämpar sig väl för uppgifter som att exponera befintlig Python-kod som ett REST-API, eller att tillhandahålla kärnan i ett webbprojekt där utvecklaren gör det mesta av det tunga jobbet.
”Pyramid gör det möjligt för dig att bli produktiv snabbt, och kommer att växa med dig”, står det i dokumentationen. ”Den kommer inte att hålla dig tillbaka när din applikation är liten, och den kommer inte att stå i vägen för dig när din applikation blir stor.”
Ett bra sätt att beskriva Pyramids minimalism skulle vara ”fri från policy”, en term som används i avsnittet i dokumentationen som diskuterar hur Pyramid står sig i förhållande till andra webbramverk. I grund och botten betyder ”fri från policy” att vilken databas eller vilket mallspråk du väljer att använda inte är Pyramids angelägenhet.
Det krävs mycket lite arbete för att bygga en grundläggande Pyramid-applikation. Precis som med Bottle och Flask kan en Pyramid-applikation bestå av en enda Python-fil, bortsett från filerna för själva ramverket. Ett enkelt API med en rutt kräver inte mer än ett tiotal rader kod. Det mesta av det är boilerplate som from … import
-angivelser och inställning av WSGI-servern.
Som standard innehåller Pyramid flera saker som är vanliga i webbapplikationer, men de tillhandahålls som komponenter som kan sättas ihop, inte som fullfjädrade lösningar. Stöd för användarsessioner, till exempel, kommer till och med med CSRF-skydd. Men stöd för användarkonton, t.ex. inloggningar eller kontohantering, ingår inte i paketet. Du måste själv utveckla det eller lägga till det med hjälp av en plug-in. Detsamma gäller för hantering av formulär och databasanslutningar.
Pyramid erbjuder till och med ett sätt att skapa mallar från tidigare Pyramidprojekt för att återanvända tidigare arbete. Dessa mallar, som kallas ”scaffolds”, genererar en Pyramid-app med enkel routing och några startmallar för HTML/CSS. Medföljande scaffolds inkluderar ett exempel på ett startprojekt och ett projekt som ansluter till databaser via det populära Pythonbiblioteket SQLAlchemy.
Pyramids smala test- och felsökningsverktyg gör susen. Om du kopplar in debugtoolbar
-tillägget i en Pyramid-app får du en klickbar ikon på varje webbsida som genererar detaljer om appens körning, inklusive en detaljerad spårning vid fel. Loggning och enhetstestning finns också med.
Pyramids dokumentation är utmärkt. Förutom en snabb rundtur i grunderna och en genomgång i stil med en handledning hittar du en uppsättning handledningar som bidragits av gemenskapen och en kokbok med vanliga recept. Den sistnämnda innehåller distributionstekniker för en mängd målmiljöer, från Google App Engine till Nginx.
Pyramid stöder både Python 2 och Python 3, men använder inte Python 3:s asynkrona syntax. Om du vill utnyttja async i Pyramid, se aiopyramid-projektet, som innehåller en byggnadsställning för en async-driven ”hello world”-applikation.
Sanic
Designad för snabbhet och enkelhet fungerar Sanic med Python 3.6 eller senare och använder Pythons async/await
-syntax (tillgänglig från och med Python 3.5) för att du ska kunna skapa effektiva webbapplikationer.
Som med Flask eller Bottle körs en grundläggande Sanic-”hallå-världen”-kod på cirka 10 rader kod, varav det mesta är import och annan boilerplate. Den viktigaste skillnaden är att programvägar måste deklareras som async def
-funktioner, och du måste använda await
för att anropa dessa funktioner i din asynkrona kod. Om du har skrivit async-drivna program tidigare har du redan den svåraste delen bakom dig.
Många av de mekanismer som Sanic använder för att hantera anslutningar och svar kommer att vara bekanta. Förfrågningar och svar är bara objekt med bekanta egenskaper, som uppladdade filer, formulär, JSON-objekt, rubriker och så vidare.
Användningar med många rutter blir otympliga att hantera. Sanic åtgärdar detta med ”blueprints”, objekt som kan beskriva grupper av rutter och låta dig hantera dem via ett gränssnitt på hög nivå. Istället för att skriva varje rutt explicit eller använda ett överskott av rutter med variabler kan du skriva några blueprints för att generiskt beskriva hur rutterna fungerar i din app (t.ex. /object/object_id/action
). Blueprints kan ha gemensam middleware, vilket är användbart om du vill tillämpa hanteringsfunktionalitet på vissa rutter men inte på andra.
Sanic fungerar även med andra protokoll än HTTP. WebSocket-slutpunkter kräver endast en annan dekorator och lite mer intern logik (t.ex. invänta och hantera svar). Anpassade nätverksprotokoll kan stödjas genom att underklassa asyncio.protocol
.
Sanic utelämnar medvetet funktionalitet som databasanslutning och HTML-templating, samtidigt som den behåller de funktioner som man skulle använda för att koppla in dessa funktioner: middleware, centraliserad applikationskonfiguration och så vidare.
Tornado
Tornado är ett annat litet ramverk som är inriktat på ett specifikt användningsfall: asynkrona nätverksapplikationer. Tornado lämpar sig väl för att skapa tjänster som öppnar ett stort antal nätverksanslutningar och håller dem vid liv – det vill säga allt som involverar WebSockets eller långa omröstningar. Tornado 6.0 kräver Python 3.5 eller högre, och avstår helt från stöd för Python 2.
Likt Bottle eller Falcon utelämnar Tornado funktioner som är ovidkommande för dess centrala syfte. Tornado har ett inbyggt templatsystem för att generera HTML och andra utdata, och tillhandahåller mekanismer för internationalisering, formulärhantering, cookie-inställning, användarautentisering och CSRF-skydd. Men den utelämnar funktioner, som formulärvalidering och en ORM, som främst är avsedda för webbprogram som vänder sig till användaren.
Tornado utmärker sig för att tillhandahålla infrastruktur till program som behöver nära kontroll över asynkrona nätverk. Tornado tillhandahåller till exempel inte bara en inbyggd asynkron HTTP-server utan även en asynkron HTTP-klient. Tornado är därför väl lämpad för att bygga appar, t.ex. en webscraper eller en bot, som frågar efter andra webbplatser parallellt och agerar på de returnerade uppgifterna.
Om du vill skapa en app som använder andra protokoll än HTTP har Tornado allt du behöver. Tornado ger tillgång till TCP-anslutningar och sockets på låg nivå till verktyg som DNS-upplösare, liksom till autentiseringstjänster från tredje part, och stöder samarbete med andra ramverk genom WSGI-standarden. Dokumentationen, som är liten men inte sparsam, innehåller gott om exempel för att åstadkomma allt detta.
Tornado både utnyttjar och kompletterar Pythons ursprungliga funktionalitet för asynkrona beteenden. Om du använder Python 3.5 har Tornado stöd för de inbyggda nyckelorden async
och await
, som lovar att ge programmen en hastighetsökning. Du kan också använda futures eller callbacks för att hantera svar på händelser.
Tornado tillhandahåller ett bibliotek med synkroniseringsprimitiver -emaphores, lås och så vidare – för att samordna händelser mellan asynkrona coroutines. Observera att Tornado normalt körs enkeltrådad, så dessa primitiv är inte samma sak som deras namngivare för trådning. Men om du vill köra Tornado i parallella processer för att utnyttja flera sockets och kärnor finns det verktyg för detta.
Tornados dokumentation täcker varje huvudkoncept i ramverket och alla de viktigaste API:erna i modellen. Även om den innehåller en exempelapplikation (en webcrawler) är den främst till för att demonstrera Tornados kömodul.