FastAPI Pythons Web-Framework, ein Mikroframework wie Flask. Zu seinen Stärken zählen hohe Leistung, einfache Schreibweise, ein Design mit starkem Fokus auf Produktionsabläufe und moderne Funktionen.
FastAPI ist auf der Schulter von Starlette geschrieben, und die asynchrone Verarbeitung ist einfach zu handhaben. Insbesondere weist es die folgenden Merkmale auf.
Ehrlich gesagt ist es [Responder] sehr ähnlich (https://github.com/taoufik07/responder). (Weil die Zeit, als es herauskam, nahe ist und der Responder auch auf Starlette basiert) Die beiden unteren sind jedoch so konzipiert, dass sie mit der Fast-API viel einfacher zu verwenden sind. Aus den folgenden Perspektiven denke ich, dass die Fast API nur für den Produktionsbetrieb gedacht ist. (Ich persönlich denke, der Responder ist einfacher zu verwenden, wenn Sie frei schreiben möchten.)
--Dokumente sind höflich (Verknüpfung mit DB, Authentifizierung, https-Konvertierung usw. werden ebenfalls eingeführt)
Ich habe auch die Leistung mit einigen Python-Frameworks verglichen und festgestellt, dass die Fast-API anscheinend eine gute Leistung erbringt. (Referenz: Vergleich der Leistung des Python-Webframeworks (Django, Flask, Responder, FastAPI, japronto))
Ich denke, das offizielle Tutorial ist angemessen, wenn Sie die Fast API schätzen möchten. Es ist sehr leicht zu verstehen, da der Inhalt umfangreich ist. Auf der anderen Seite ist es jedoch ein wenig quantitativ schwer, sich darauf zu beziehen, nur um loszulegen. Daher möchte ich den Inhalt neu organisieren und einführen, damit die Fast API mit dem erforderlichen Minimum verwendet werden kann.
Darüber hinaus wurde dieser Artikel unter der folgenden Annahme verfasst.
Codebeispiele, die den hier vorgestellten Inhalten entsprechen, sind in hier zusammengefasst. Bitte verwenden Sie es, wenn Sie nur Swagger berühren möchten.
intro install FastAPI Installieren Sie fastapi und seinen ASGI-Server uvicorn.
$ pip install fastapi uvicorn
intro code
Lassen Sie uns eine API erstellen, die {{text ":" Hallo Welt! "}`
In json zurückgibt, wenn GET.
intro.py
from fastapi import FastAPI
app = FastAPI()
@app.get('/') #Angabe der Methode und des Endpunkts
async def hello():
return {"text": "hello world!"}
Ich denke, es ist dasjenige, das im Python-Mikroframework präzise geschrieben werden kann.
run server
Der Server wird wie folgt gestartet. (--Reload ist während der Entwicklung praktisch, da der Server jedes Mal aktualisiert wird, wenn die Datei geändert wird.) `Intro: app``` Teil ist`
Dateiname: FastAPI () Instanzname
ist. Bitte ersetzen Sie gegebenenfalls.
$ uvicorn intro:app --reload
Gehen Sie zu http://127.0.0.1:8000/docs. Dadurch wird die Swagger-Benutzeroberfläche geöffnet. Sie können die API hier klicken.
Sie können die Anforderungs- und Antwortschemata auch mit der unten beschriebenen Methode überprüfen. Eine der großen Stärken von FastAPI ist, dass dieses Dokument automatisch generiert wird. Wenn Sie normal entwickeln, wird das Dokument ohne Erlaubnis generiert.
Die folgenden Elemente werden behandelt.
GET method
Sie können Parameter abrufen, indem Sie den Parameternamen in das Argument einfügen. Einmal
`/ {param}`
deklarierte Parametername ist ** Pfadparameter **Bitte verstehe. Auch die Reihenfolge der Argumente spielt keine Rolle. Abhängig davon, ob der Standardwert deklariert ist oder nicht, ändert sich dann die Verarbeitung, wenn der im Argument enthaltene Parameter zum Zeitpunkt von GET nicht enthalten ist.
`{" detail ":" Not Found "}`
zurückgegeben.Die Funktion von Fast API besteht darin, dem Argument wie folgt einen ** Typ-Hinweis ** von Python hinzuzufügen.
@app.get('/get/{path}')
async def path_and_query_params(
path: str,
query: int,
default_none: Optional[str] = None):
return {"text": f"hello, {path}, {query} and {default_none}"}
Auf diese Weise berücksichtigt die Fast-API beim Abrufen des Parameters den Python-Typ-Hinweis.
`{" detail ":" Not Found "}`
zurück, wenn eine Konvertierung in den angegebenen Typ nicht möglich isthalten. Wenn Sie Swagger tatsächlich aktivieren, können Sie die Informationen zum Parametertyp wie unten gezeigt überprüfen.
validation Darüber hinaus können Sie mithilfe der folgenden Abfrage und des folgenden Pfads einige erweiterte Aufgaben ausführen. Die Abfrage bezieht sich auf den Abfrageparameter und der Pfad auf den Pfadparameter.
from fastapi import Query, Path
Verwenden Sie wie folgt. Sie können grundsätzlich dieselben Argumente für Abfrage und Pfad verwenden.
`...`
, wenn Sie keinen Standardwert haben möchten (erforderlich)
--alias: Geben Sie den Parameternamen an. Es wird verwendet, wenn Sie den Argumentnamen und den Parameternamen trennen möchten. Wenn es gegen die Python-Namenskonvention verstößt
--Sonstiges: Sie können die Zeichenlänge, den regulären Ausdruck und den Wertebereich angeben, um den empfangenen Wert zu begrenzen.@app.get('/validation/{path}')
async def validation(
string: str = Query(None, min_length=2, max_length=5, regex=r'[a-c]+.'),
integer: int = Query(..., gt=1, le=3), # required
alias_query: str = Query('default', alias='alias-query'),
path: int = Path(10)):
return {"string": string, "integer": integer, "alias-query": alias_query, "path": path}
Sie können auch die Einschränkungen von Swagger überprüfen. Da Sie die API aufrufen können, versuchen Sie, den Wert auf verschiedene Arten zu ändern, und überprüfen Sie, ob die Validierung korrekt durchgeführt wurde. POST method
Erklärt, wie Postdaten empfangen werden. Bereiten Sie nach dem Erben von `` `pydantic.BaseModel``` zunächst eine separate Klasse mit Typhinweisen für Attribute vor und fügen Sie Typhinweise mit Argumenten als Typ des Anforderungshauptteils hinzu. Das ist gut.
from pydantic import BaseModel
from typing import Optional, List
class Data(BaseModel):
"""Klasse mit Typhinweisen für Anforderungsdaten"""
string: str
default_none: Optional[int] = None
lists: List[int]
@app.post('/post')
async def declare_request_body(data: Data):
return {"text": f"hello, {data.string}, {data.default_none}, {data.lists}"}
Hier setzt der obige Code voraus, dass der folgende JSON veröffentlicht wird.
requestBody
{
"string": "string",
"default_none": 0,
"lists": [1, 2]
}
Wenn nicht genügend Felder vorhanden sind, wird der Statuscode 422 zurückgegeben. (Wenn es ein zusätzliches Feld gibt, scheint es normal zu funktionieren) Nachdem die Verarbeitung bis zu diesem Punkt durchgeführt wurde, kann die Datenstruktur des erwarteten Anforderungshauptteils über die Swagger-Benutzeroberfläche bestätigt werden.
embed request body Etwas anders als im vorherigen Beispiel werde ich die Notation für die folgende Datenstruktur erläutern.
requestBody
{
"data": {
"string": "string",
"default_none": 0,
"lists": [1, 2]
}
}
Verwenden Sie für eine solche Struktur dieselbe Datenklasse wie zuvor. Nur die Struktur kann mit `fastapi.Body``` geändert werden.
fastapi.Body``` ist ein Begleiter von
pydantic.Query```, das bei der Validierung der GET-Methode eingeführt wurde. Ebenso ist das erste Argument der Standardwert. Es wird ein Argument namens Embed verwendet, das in
`pydantic.Query``` nicht gefunden wurde. Die Struktur kann mit den folgenden geringfügigen Änderungen geändert werden.
from fastapi import Body
@app.post('/post/embed')
async def declare_embedded_request_body(data: Data = Body(..., embed=True)):
return {"text": f"hello, {data.string}, {data.default_none}, {data.lists}"}
nested request body Als nächstes werde ich erklären, wie die Struktur verschachtelter Listen und Wörterbücher wie folgt behandelt wird. Die Struktur von subData besteht aus einem eingebetteten Anforderungshauptteil, aber ich werde eine andere Schreibweise einführen.
{
"subData": {
"strings": "string",
"integer": 0
},
"subDataList": [
{"strings": "string0", "integer": 0},
{"strings": "string1", "integer": 1},
{"strings": "string2", "integer": 2}
]
}
Verschachtelte Typdeklarationen sind häufig sehr grob mit Hinweisen zum Python-Typ. (Wenn Sie sich eine ungefähre Vorstellung machen möchten, reicht es aus, die folgende Unterdatenliste wie `List [Any]`
oder List [Dict [str, Any]
`einzugeben.)
Andererseits kann FastAPI (oder pydantic) komplexe verschachtelte Strukturen verarbeiten.
Sie können Unterklassen entlang der verschachtelten Struktur genau definieren und Typhinweise hinzufügen, wie unten gezeigt.
class subDict(BaseModel):
strings: str
integer: int
class NestedData(BaseModel):
subData: subDict
subDataList: List[subDict]
@app.post('/post/nested')
async def declare_nested_request_body(data: NestedData):
return {"text": f"hello, {data.subData}, {data.subDataList}"}
validation
Was Sie mit der GET-Methode tun können und was Sie tun können, ist fast dasselbe. Der Unterschied besteht darin, dass `pydantic.Field``` anstelle von`
fastapi.Query verwendet wird. Aber die Argumente sind die gleichen. Ich habe gerade `` `pydantic.Field
für jede Klasse eingeführt, die im verschachtelten Anforderungshauptteil verwendet wird. Sie können es auch mit `` `fastapi.Query``` usw. verwenden, es wird jedoch das Argumentbeispiel verwendet. Die an dieses Argument übergebenen Daten sind der Standardwert, wenn die API von Swagger aufgerufen wird.
from pydantic import Field
class ValidatedSubData(BaseModel):
strings: str = Field(None, min_length=2, max_length=5, regex=r'[a-b]+.')
integer: int = Field(..., gt=1, le=3) # required
class ValidatedNestedData(BaseModel):
subData: ValidatedSubData = Field(..., example={"strings": "aaa", "integer": 2})
subDataList: List[ValidatedSubData] = Field(...)
@app.post('/validation')
async def validation(data: ValidatedNestedData):
return {"text": f"hello, {data.subData}, {data.subDataList}"}
Sie können auch eine Klasse wie die im Anforderungshauptteil für die Antwort definierte definieren und eine Validierung durchführen.
Wenn Sie es standardmäßig an response_model übergeben
Wenn Sie hier wie folgt schreiben, wird `integer``` aus dem zurückgegebenen Wörterbuch entfernt und`
aux``` wird ergänzt, um json zurückzugeben. (Es wird ein sehr einfaches Beispiel angegeben. Wenn es jedoch verschachtelt ist oder eine etwas komplizierte Validierung erforderlich ist, können Sie die Notation für Typhinweise verwenden, wie unter "Behandlung von Anforderungen" angegeben.)
class ItemOut(BaseModel):
strings: str
aux: int = 1
text: str
@app.get('/', response_model=ItemOut)
async def response(strings: str, integer: int):
return {"text": "hello world!", "strings": strings, "integer": integer}
In dieser Phase können Sie das Schema der Antwortdaten von Swagger überprüfen.
Es gibt verschiedene Optionen für die Verwendung von response_model.
#Antwort, wenn nicht im Wörterbuch_Der Standardwert der Attribute des Modells"Ich kann es nicht hineinstecken"
@app.get('/unset', response_model=ItemOut, response_model_exclude_unset=True)
async def response_exclude_unset(strings: str, integer: int):
return {"text": "hello world!", "strings": strings, "integer": integer}
# response_des Modells"strings", "aux"Ignorieren-> "text"Nur zurück
@app.get('/exclude', response_model=ItemOut, response_model_exclude={"strings", "aux"})
async def response_exclude(strings: str, integer: int):
return {"text": "hello world!", "strings": strings, "integer": integer}
# response_des Modells"text"Nur berücksichtigen-> "text"Nur zurück
@app.get('/include', response_model=ItemOut, response_model_include={"text"})
async def response_include(strings: str, integer: int):
return {"text": "hello world!", "strings": strings, "integer": integer}
Es gibt drei Stufen der Statuscodeverwaltung.
from fastapi import HTTPException
from starlette.responses import Response
from starlette.status import HTTP_201_CREATED
@app.get('/status', status_code=200) #Standardstatuscode-Spezifikation
async def response_status_code(integer: int, response: Response):
if integer > 5:
# error handling
raise HTTPException(status_code=404, detail="this is error messages")
elif integer == 1:
# set manually
response.status_code = HTTP_201_CREATED
return {"text": "hello world, created!"}
else:
# default status code
return {"text": "hello world!"}
background process Sie können den Hintergrundprozess verwenden, um nur die Antwort zurückzugeben, bevor die schwere Verarbeitung abgeschlossen ist. Dieser Prozess ist für WSGI-Systeme (Django usw.) ziemlich schwierig. Starlette-basiertes ASGI macht diesen Prozess jedoch sehr präzise.
Das Verfahren ist
Es ist schwer vorherzusagen, was los ist, aber ich denke, die Beschreibung selbst ist einfach.
Versuchen Sie als Beispiel für eine umfangreiche Verarbeitung, einen Hintergrundprozess auszuführen, der für die empfangenen Pfadparameter Sekunden in den Ruhezustand versetzt und dann gedruckt wird.
from fastapi import BackgroundTasks
from time import sleep
from datetime import datetime
def time_bomb(count: int):
sleep(count)
print(f'bomb!!! {datetime.utcnow()}')
@app.get('/{count}')
async def back(count: int, background_tasks: BackgroundTasks):
background_tasks.add_task(time_bomb, count)
return {"text": "finish"} # time_Gibt eine Antwort zurück, ohne auf das Ende der Bombe zu warten
Die Ergebnisse werden in der folgenden Reihenfolge verarbeitet
Es scheint also, dass es im Hintergrund richtig verarbeitet wird.
unittest Der TestClient von Starlette ist ausgezeichnet und Sie können die API leicht für unittest drücken. Dieses Mal werde ich einen Unit-Test mit Pytest gemäß dem Tutorial durchführen.
install
$ pip install requests pytest
├── intro.py
└── tests
├── __init__.py
└── test_intro.py
Lassen Sie uns nun den folgenden Komponententest durchführen.
intro.py
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional, List
app = FastAPI()
@app.get('/')
async def hello():
return {"text": "hello world!"}
class Data(BaseModel):
string: str
default_none: Optional[int] = None
lists: List[int]
@app.post('/post')
async def declare_request_body(data: Data):
return {"text": f"hello, {data.string}, {data.default_none}, {data.lists}"}
unittest
Das Verkaufsargument ist, dass Sie mit `starlette.testclient.TestClient
einfach GET und POST drücken und
`` assert``` der Antwort erhalten können, wie unten gezeigt.
test_intro.py
from starlette.testclient import TestClient
from intro import app
# get and assign app to create test client
client = TestClient(app)
def test_read_hello():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"text": "hello world!"}
def test_read_declare_request_body():
response = client.post(
"/post",
json={
"string": "foo",
"lists": [1, 2],
}
)
assert response.status_code == 200
assert response.json() == {
"text": "hello, foo, None, [1, 2]",
}
$ pytest
========================= test session starts =========================
platform darwin -- Python 3.6.8, pytest-5.3.2, py-1.8.1, pluggy-0.13.1
rootdir: ***/***/***
collected 1 items
tests/test_intro.py . [100%]
========================== 1 passed in 0.44s ==========================
deployment Sie haben folgende Möglichkeiten: Es ist eine einfache Anwendung, daher denke ich nicht, dass es Probleme mit der Infrastruktur geben wird.
Wenn Sie Docker verwenden können, ist die letztere Methode grundsätzlich besser, und wenn dies nicht der Fall ist (z. B. das Erstellen einer schnellen API mit PaaS), ist die erstere Methode besser.
In Bezug auf die Besonderheiten gibt es keine für FastAPI spezifische Verarbeitung, und es handelt sich um ein Verfahren, das nicht mit anderen Mikroframeworks zusammenhängt. Daher werde ich es dieses Mal weglassen. Referenz:
Hier finden Sie eine Referenz für andere häufig verwendete Einstellungen und kontextsensitive Themen, die nicht als Lernprogramm geschrieben werden müssen. - CORS-Problem (Cross-Origin Resource Sharing) behoben: Dies ist ein Problem, das auftritt, wenn sich das Frontend auf einem anderen Server als das Backend befindet. Authentifizierung: Enthält Beispiele für die OAuth2- und HTTP-Basisauthentifizierung. Dokumente werden automatisch zur Authentifizierung generiert. Zusammenfassung Dies ist das Ende des Mindest-Lernprogramms. Sie sollten nun in der Lage sein, eine vollständige API-Server-> Bereitstellung zu entwickeln.
Zusätzlich zu den Inhalten, die in dieser Zeit behandelt wurden, reicht es meiner Meinung nach aus, nur auf die zugehörigen Kapitel zu verweisen, wenn Sie sich mit Datenbankverknüpfungen, HTML-Rendering, Websocket, GraphQL usw. befassen möchten.
Wie auch immer, es ist praktisch, dass Swagger automatisch generiert wird. Probieren Sie es also aus, während Sie Ihre Hände bewegen!
Obwohl es wenig mit dem Inhalt dieses Artikels zu tun hat, möchte ich schließlich die interessantesten Kapitel in der offiziellen Fast API-Dokumentation vorstellen. Der Entwicklungsprozess und die Punkte, die ihn von anderen Frameworks unterscheiden, werden erwähnt.
Refs
Was das Front-Miso betrifft, habe ich zuvor versucht, eine Schemadefinition-> Prahlerei mit dem Responder zu generieren, aber die Menge der Beschreibung war völlig anders. (Da es keine Beschreibung von FastAPI nur für Swagger gibt) hier können Sie sehen, wie erstaunlich FastAPI ist. Ich glaube du kannst.
Recommended Posts