Dlaczego warto używać FastAPI
Python zawsze był popularny, jeśli chodzi o tworzenie lekkich aplikacji webowych dzięki takim frameworkom, jak Flask, Django, Falcon i wiele innych. Ze względu na pozycję Pythona jako języka numer jeden w uczeniu maszynowym, jest on szczególnie przydatny przy opakowywaniu modeli i prezentowaniu ich jako usługi. Przez wiele lat Flask był tutaj czołowym narzędziem, ale powoli zostaje on wypierany przez FastAPI. Jest to stosunkowo nowy framework webowy dla Pythona, który czerpie inspirację od swoich poprzedników, udoskonalając i naprawiając wiele ich wad.
FastAPI jest zbudowany na Starlette i ma wiele świetnych funkcji. Zyskał on ostatnio dużą popularność, a po spędzeniu ostatnich 8 miesięcy na codziennej pracy z nim, mogę śmiało powiedzieć, że cały ten szum wokół niego jest uzasadniony. Chciałbym Wam podać pięć powodów, dla których warto spróbować z FastAPI.
Prosty, ale genialny interfejs
Wszystkie frameworki webowe muszą balansować między funkcjami, a dawaniem programiście wolności. Django dostarcza mnóstwo funkcji, ale jednocześnie narzuca dość sztywny sposób robienia większości rzeczy. Z drugiej strony Flask jest na tyle niskopoziomowy, aby zapewnić duży stopień swobody, ale użytkownikowi pozostaje potem wiele do zrobienia. FastAPI jest bardziej podobny do Flaska, jednak udaje mu się osiągnąć większą i zdrowszą równowagę.
Zobaczmy dla przykładu, jak w FastAPI definiowany jest punkt końcowy.
from fastapi import FastAPI
from pydantic import BaseModel
class User(BaseModel):
email: str
password: str
app = FastAPI()
@app.post("/login")
def login(user: User):
# ...
# do some magic
# ...
return {"msg": "login successful"}
Pydantic jest wykorzystywana do zdefiniowania schematu. Jest to niesamowita biblioteka Pythona, używana do walidacji danych. Tutaj wygląda to prosto, ale w tle dzieje się bardzo wiele. Odpowiedzialność za sprawdzenie poprawności danych wejściowych jest delegowana do FastAPI. Jeśli żądanie nie jest poprawne (na przykład pole wiadomości e-mail zawiera int
), to zamiast awarii aplikacji z przerażającym Internal Server Error (500), zwrócony zostanie odpowiedni kod błędu. Jest to też bardzo proste do zrobienia.
Ta prosta aplikacja może zostać obsłużona przez uvicorn
:
uvicorn main:app
Teraz aplikacja jest gotowa do przyjmowania żądań. W takim przypadku wyglądałoby to następująco:
curl -X POST "http://localhost:8000/login" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"email\":\"string\",\"password\":\"string\"}"
Wisienką na torcie jest to, że FastAPI automatycznie generuje dokumentację zgodną z OpenAPI przy użyciu interaktywnego Swagger UI.
Swagger UI dla aplikacji FastAPI
Async
Jedną z największych wad frameworków webowych Python WSGI w porównaniu do tych w Node.js czy Go była niemożność asynchronicznej obsługi żądań.
Od czasu wprowadzenia ASGI nie stanowi to już jednak problemu, a FastAPI w pełni to wykorzystuje. Wszystko, co musisz zrobić, to po prostu zadeklarować punkty końcowe za pomocą słowa kluczowego async
w następujący sposób:
@app.post("/")
async def endpoint():
# ...
# call async functions here with `await`
# ...
return {"msg": "FastAPI is awesome!"}
Wstrzykiwanie zależności
FastAPI ma naprawdę fajny sposób na zarządzanie zależnościami. Chociaż nie jest to wymuszane na programistach, to zdecydowanie zaleca się używanie wbudowanego systemu wstrzykiwania do obsługi zależności w punktach końcowych. Jako przykład napiszemy punkt końcowy, w którym użytkownicy mogą publikować komentarze do niektórych artykułów.
from fastapi import FastAPI, Depends
from pydantic import BaseModel
class Comment(BaseModel):
username: str
content: str
app = FastAPI()
database = {
"articles": {
1: {
"title": "Top 3 Reasons to Start Using FastAPI Now",
"comments": []
}
}
}
def get_database():
return database
@app.post("/articles/{article_id}/comments")
def post_comment(article_id: int, comment: Comment, database = Depends(get_database)):
database["articles"][article_id]["comments"].append(comment)
return {"msg": "comment posted!"}
FastAPI automatycznie ewaluuje funkcję get_database
w czasie uruchamiania, gdy wywoływany jest punkt końcowy, więc jeśli chcesz, możesz użyć zwracanej wartości. Istnieją ku temu przynajmniej dwa dobre powody.
- Zależności można zastąpić globalnie, modyfikując słownik
app.dependency_overrides
. Być może sprawi to, że testowanie będzie proste, ponieważ można wtedy łatwo mockować obiekty. - Zależność (którą w naszym przypadku jest
get_database
) może wykonywać bardziej wyrafinowane testy, pozwalając oddzielić je od logiki biznesowej. Znacznie upraszcza to sprawę. W taki sposób można na przykład łatwo zaimplementować uwierzytelnianie użytkownika.
Prosta integracja z bazami danych
FastAPI nie zmusza Cię do budowania aplikacji wokół jakiejś bazy danych (niezależnie od tego, czy chodzi o SQL, MongoDB, czy Redis). Jeśli ktoś z Was próbował pracować z MongoDB przy użyciu Django, to wie, jakie to bolesne.
Dzięki FastAPI nie musisz wkładać dużo dodatkowej pracy, ponieważ dodawanie bazy danych do stosu jest tak proste, jak to tylko możliwe (lub, mówiąc dokładniej, ilość pracy do wykonania zależy od wybranej bazy danych, a nie od komplikacji dodanych przez framework).
Spójrzcie jednak:
from fastapi import FastAPI, Depends
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine("sqlite:///./database.db")
Session = sessionmaker(bind=engine)
def get_db():
return Session()
app = FastAPI()
@app.get("/")
def an_endpoint_using_sql(db = Depends(get_db)):
# ...
# do some SQLAlchemy
# ...
return {"msg": "an exceptionally successful operation!"}
No i proszę! Już widzę, jak to piszecie
pip install fastapi
w swoim terminalu.
Obsługa GraphQL
REST może być poważną przeszkodą przy pracy ze złożonym modelem danych. Nikt się raczej nie śmieje, gdy drobna zmiana w interfejsie wymaga zaktualizowania schematu punktu końcowego. W takich sytuacjach sprawdza się GraphQL.
Chociaż obsługa GraphQL nie jest niczym nowym wśród frameworków webowych Pythona, Graphene i FastAPI współpracują ze sobą bezproblemowo. Nie ma potrzeby instalowania rozszerzeń, takich jak graphene_django
dla Django, bo wszystko działa natywnie.
+1: Świetna dokumentacja
Świetny framework nie będzie już taki świetny bez równie świetnej dokumentacji. Django, Flask i wszystkie inne frameworki są tutaj liderami, ale FastAPI jest z nimi na równi. Ponieważ FastAPI jest znacznie młodsze, to nie ma jeszcze o nim jeszcze żadnych książek, ale to tylko kwestia czasu.
Jeśli chcesz zobaczyć FastAPI w akcji, mam dla Ciebie idealny przewodnik! Napisałem szczegółowy tutorial, w którym możesz wdrożyć model uczenia maszynowego za pomocą Docker, Docker Compose i GitHub Actions.
Podsumowując, czy szukasz szybkiego i lekkiego frameworku do serwowania swoich modeli uczenia maszynowego, czy czegoś bardziej złożonego, to FastAPI Ci to zapewni. Jeśli jeszcze nie próbowaliście pracy z nim, to gorąco do tego zachęcam. Jestem pewny, że Wam się spodoba.
Oryginał tekstu w języku angielskim możesz przeczytać tutaj.