Topp 5 asynkrona webbramverk för Python

By rik

Asynkron programmering har etablerat sig som en central del av Python. För webbutvecklare finns det nu ett imponerande utbud av ramverk att välja mellan!

Vid denna tidpunkt är asynkron programmering inte bara ett populärt samtalsämne inom Python-gemenskapen. Med lanseringen av asyncio-biblioteket i version 3.5, erkände Python Node.js inflytande på webbutveckling och introducerade två nya nyckelord i språket: async och await. Detta var en betydande händelse eftersom Python-språket är mycket försiktigt med att utöka sin kärnsyntax om det inte finns ett omedelbart behov. Det understryker hur fundamentalt viktiga Python-utvecklarna ansåg de asynkrona funktionerna.

Detta banade väg för en snabb utveckling inom asynkron programmering. Både nya och befintliga bibliotek började utnyttja coroutines-funktionen. Asynkrona ramverk växte snabbt i popularitet och nya ramverk utvecklas än idag. Prestanda som är i nivå med eller bättre än Node.js är inte ovanligt. Så länge dina arbetsbelastningar inte involverar en stor mängd CPU-krävande uppgifter, finns det ingen anledning att du inte kan hantera tusentals förfrågningar per sekund.

Men nu nog med motivation!

Låt oss utforska det aktuella Python-landskapet och granska några av de mest framstående asynkrona ramverken.

Tornado

Överraskande nog är Tornado inget nytt ramverk alls. Den första versionen släpptes 2009 (alltså exakt tio år sedan, vid tidpunkten för denna text) och fokus har sedan dess varit att erbjuda robust asynkron programmering med hög samtidighet.

Tornado är i grunden inte ett webbramverk, utan snarare en samling asynkrona moduler som även används för att bygga webbramverksmodulen. Mer specifikt består dessa moduler av:

  • Coroutines och andra grundläggande byggstenar (tornado.gen, tornado.locks, tornado.queues, etc.)
  • Nätverksmoduler (tornado.ioloop, tornado.iostream, etc.)
  • Asynkrona servrar och klienter (tornado.httpserver, tornado.httpclient, etc.)

Dessa moduler har kombinerats för att skapa de slutliga ramverksmodulerna: tornado.web, tornado.routing, tornado.template, etc.

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
    ])

if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()
  

Tornado har en stark och engagerad anhängarskara i Python-communityt och används av erfarna arkitekter för att bygga mycket kraftfulla system. Det är ett ramverk som länge har haft lösningen på problem med samtidighet, men som kanske inte har blivit mainstream eftersom det inte stöder WSGI-standarden och var en betydande investering (kom ihåg att majoriteten av Python-bibliotek fortfarande är synkrona).

Sanic

Sanic är ett ”modernt” ramverk i ordets rätta bemärkelse. Det stöder inte Python-versioner under 3.6, har ett inbyggt stöd för den enkla syntaxen async/await och kräver inte att man läser igenom massvis med dokumentation och hanterar komplexa fall innan man kan skriva sin första HTTP-hanterare.

Resultatet är en behaglig syntax (enligt mig). Den liknar koden du skulle skriva med andra mikro-ramverk (som Flask, CherryPy), med bara några få async-konstruktioner insprängda:

from sanic import Sanic
from sanic.response import json

app = Sanic()

@app.route("/")
async def test(request):
    return json({"hello": "world"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)
  

Sanic är utan tvekan det populäraste och mest omtyckta asynkrona ramverket i Python-världen. Det erbjuder nästan alla funktioner du kan tänkas behöva för dina projekt – routing, middleware, cookies, versionshantering, blueprints, klassbaserade vyer, statiska filer, streaming, sockets etc. Och det som inte erbjuds direkt – mallar, databasstöd, fil-I/O, köer – kan enkelt läggas till eftersom det nu finns ett stort utbud av asynkrona bibliotek för dessa ändamål.

Vibora

Vibora är en nära släkting till Sanic, med skillnaden att dess fokus ligger på att vara den snabbaste Python-webbservern på marknaden. Det första som möter dig på dess webbplats är en jämförelse mellan olika ramverk:

Som du kan se hävdar Vibora att vara flera gånger snabbare än de klassiska ramverken och mer än dubbelt så snabb som Sanic, dess närmaste konkurrent. Självklart bör prestandatester alltid tas med en nypa salt. 🙂

Trots att Vibora i sin syntax och funktionalitet är jämförbar med Sanic (eller kanske till och med något bättre eftersom den innehåller populära bibliotek och funktioner som mallar är tillgängliga direkt), anser jag att Sanic är mer mogen på grund av sin längre historia och större community.

from vibora import Vibora, JsonResponse

app = Vibora()

@app.route('/')
async def home():
    return JsonResponse({'hello': 'world'})

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=8000)

Men om du är en prestandaentusiast kan Vibora vara något för dig. Men vid tidpunkten för denna text genomgår Vibora en fullständig omskrivning för att bli ännu snabbare, och länken till dess prestandaversion anger att den är under ”intensiv utveckling”. Detta kan vara en besvikelse för de som använde Vibora tidigare och snart kommer att möta icke-kompatibla förändringar, men det är fortfarande tidiga dagar för asynkron programmering i Python, och stabilitet kan inte förväntas.

Quart

Om du gillar att utveckla med Flask men saknar asynkront stöd, kommer du att uppskatta Quart mycket.

Quart är kompatibelt med ASGI-standarden, som är en efterföljare till den välkända WSGI-standarden och erbjuder stöd för asynkronitet. Det intressanta med Quart är att det inte bara liknar Flask, utan faktiskt är kompatibelt med Flask API! Skaparen av ramverket ville behålla känslan av Flask och bara lägga till asynk, WebSockets och HTTP 2-stöd. Som ett resultat kan du lära dig Quart direkt från Flask-dokumentationen, men kom ihåg att funktionerna i Quart är asynkrona.

from quart import Quart

app = Quart(__name__)

@app.route('/')
async def hello():
    return 'hello'

app.run()
  

Känns (nästan) exakt som Flask, eller hur?!

Eftersom Quart är en vidareutveckling av Flask är alla funktioner i Flask tillgängliga: routing, middleware, sessioner, mallar, blueprints och så vidare. Du kan faktiskt även använda Flask-tillägg direkt i Quart. En nackdel är att endast Python 3.7+ stöds, men om du inte använder den senaste Python-versionen är asynkronisering kanske inte rätt väg för dig. 🙂

Dokumentationen kan vara bristfällig om du inte har tidigare erfarenhet av Flask, men jag rekommenderar Quart eftersom det förmodligen är det enda asynkrona ramverket som snart kommer att släppa version 1.0.

FastAPI

Det sista (men mest imponerande) ramverket på den här listan är FastAPI. Det är inte bara ett API-ramverk, utan faktiskt det mest funktionsrika och väldokumenterade ramverk jag stött på i min undersökning av asynkrona Python-ramverk.

Det är intressant att notera att skaparen av ramverket har studerat flera andra ramverk grundligt, från samtida som Django till moderna som Sanic, samt undersökt tekniker i NestJS (ett webbramverk för Node.js och Typescript). Deras utvecklingsfilosofi och omfattande jämförelser kan du läsa här.

Syntaxen är ganska tilltalande; man kan till och med hävda att den är roligare att använda än de andra ramverken vi har granskat:

from fastapi import FastAPI

app = FastAPI()

@app.get("/users/me")
async def read_user_me():
    return {"user_id": "the current user"}

@app.get("/users/{user_id}")
async def read_user(user_id: str):
    return {"user_id": user_id}

Och nu, listan över de avgörande funktioner som gör att FastAPI sticker ut:

Automatisk generering av API-dokumentation: Så snart dina slutpunkter är definierade kan du enkelt interagera med API:et genom ett standardiserat användargränssnitt. SwaggerUI, ReDoc och andra är stödda.

Ramverket genererar också automatisk dokumentation för datamodeller med JSON Schema.

Modern utveckling: Ja, ordet ”modern” används flitigt, men jag upplever att FastAPI verkligen lever upp till det. Beroendeinjektion och typ-tips är centrala, vilket inte bara främjar god kodningspraxis utan även hjälper till att förhindra buggar och förvirring på lång sikt.

Omfattande dokumentation: Jag vet inte hur det är med dig, men jag värdesätter verkligen bra dokumentation. På den punkten vinner FastAPI stort. Dokumentationen är omfattande och förklarar nästan varje subtil detalj och potentiella fallgropar för utvecklare på alla nivåer. Jag känner verkligen att ”hjärta och själ” har lagts ned i dokumentationen, och den enda jämförelsen jag kan göra är med Django-dokumentationen (ja, FastAPI-dokumentationen är så bra!).

Utöver grunderna: FastAPI stöder WebSockets, streaming och GraphQL, samt alla traditionella funktioner som CORS, sessioner, cookies och så vidare.

Och hur är det med prestanda? FastAPI är byggt på det imponerande Starlette-biblioteket, vilket resulterar i prestanda som kan mäta sig med Node, och i vissa fall till och med Go! Sammanfattningsvis tror jag att FastAPI kommer att etablera sig som det bästa asynkrona ramverket för Python.

Slutsats

Det händer mycket inom Python asynkron-landskapet just nu. Nya ramverk dyker upp, gamla skrivs om och bibliotek utvecklas för att passa asynkron funktionalitet. Även om Python har inbyggt stöd för en händelseloop och det är möjligt att göra delar av din applikation asynkron, kan du välja att satsa fullt ut och bygga vidare på något av de ramverk som beskrivs här. Se bara till att tänka långsiktigt: flera av de asynkrona Python-ramverken är fortfarande i ett tidigt utvecklingsstadium och utvecklas snabbt, vilket kan påverka din utvecklingsprocess och öka kostnaderna. Försiktighet är viktigt!

Men oavsett vad, Python är redo för produktion och kan leverera hög prestanda när det gäller webbramverk. Om du länge har funderat på att migrera till Node, behöver du inte göra det nu! 🙂

Låter det intressant? Lär dig Python idag!