上一篇 FastAPI 構(gòu)建 API 高性能的 web 框架(一)是把LLM模型使用Fastapi的一些例子,本篇簡(jiǎn)單來(lái)看一下FastAPI的一些細(xì)節(jié)。
有中文官方文檔:fastapi中文文檔
假如你想將應(yīng)用程序部署到生產(chǎn)環(huán)境,你可能要執(zhí)行以下操作:
pip install fastapi
并且安裝uvicorn來(lái)作為服務(wù)器:
pip install "uvicorn[standard]"
然后對(duì)你想使用的每個(gè)可選依賴項(xiàng)也執(zhí)行相同的操作。
1 基礎(chǔ)使用
參考:https://fastapi.tiangolo.com/zh/tutorial/body-multiple-params/
1.1 單個(gè)值Query的使用
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
這里Union[str, None]
代表參數(shù)q,可以是字符型也可以None不填,Query用來(lái)更多的補(bǔ)充信息,比如這個(gè)參數(shù),默認(rèn)值是None,最大長(zhǎng)度50
1.2 多個(gè)參數(shù)
from typing import Annotated
from fastapi import FastAPI, Path
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
# 檢查項(xiàng),不同key要遵從什么格式
name: str
description: str | None = None # 字符或者None都可以,默認(rèn)None
price: float
tax: float | None = None # 數(shù)值或者None都可以,默認(rèn)None
@app.put("/items/{item_id}")
async def update_item(
item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)], # item_id是一個(gè)路徑,通過(guò)Annotated需要兩次驗(yàn)證,驗(yàn)證一,是否是整數(shù)型,驗(yàn)證二,數(shù)值大小 大于等于0,小于等于1000
q: str | None = None,
item: Item | None = None, # 格式遵從class Item類且默認(rèn)為None
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
if item:
results.update({"item": item})
return results
1.3 請(qǐng)求參數(shù) Field
pydantic中比較常見(jiàn)
from typing import Annotated
from fastapi import Body, FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = Field(
default=None, title="The description of the item", max_length=300
)
# 跟Query比較相似,設(shè)置默認(rèn),title解釋,最大長(zhǎng)度300
price: float = Field(gt=0, description="The price must be greater than zero")
# price大于0,且是float形式
tax: float | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
results = {"item_id": item_id, "item": item}
return results
1.4 響應(yīng)模型response_model
參考:https://fastapi.tiangolo.com/zh/tutorial/response-model/
from typing import Any
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: str | None = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: str | None = None
@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn) -> Any:
return user
response_model是控制輸出的內(nèi)容,按照規(guī)定的格式輸出,作用概括為:
- 將輸出數(shù)據(jù)轉(zhuǎn)換為其聲明的類型。
- 校驗(yàn)數(shù)據(jù)。
- 在 OpenAPI 的路徑操作中為響應(yīng)添加一個(gè) JSON Schema。
- 并在自動(dòng)生成文檔系統(tǒng)中使用。
1.5 請(qǐng)求文件UploadFile
https://fastapi.tiangolo.com/zh/tutorial/request-files/
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: bytes = File()):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
return {"filename": file.filename}
UploadFile 與 bytes 相比有更多優(yōu)勢(shì):
- 這種方式更適于處理圖像、視頻、二進(jìn)制文件等大型文件,好處是不會(huì)占用所有內(nèi)存;
- 可獲取上傳文件的元數(shù)據(jù);
1.6 CORS(跨域資源共享)
https://fastapi.tiangolo.com/zh/tutorial/cors/
你可以在 FastAPI 應(yīng)用中使用 CORSMiddleware 來(lái)配置它。
- 導(dǎo)入 CORSMiddleware。
- 創(chuàng)建一個(gè)允許的源列表(由字符串組成)。
- 將其作為「中間件」添加到你的 FastAPI 應(yīng)用中。
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"http://localhost.tiangolo.com",
"https://localhost.tiangolo.com",
"http://localhost",
"http://localhost:8080",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
async def main():
return {"message": "Hello World"}
- allow_origins - 一個(gè)允許跨域請(qǐng)求的源列表。例如 [‘https://example.org’, ‘https://www.example.org’]。你可以使用 [‘*’] 允許任何源。
1.7 與SQL 通信
https://fastapi.tiangolo.com/zh/tutorial/sql-databases/
FastAPI可與任何數(shù)據(jù)庫(kù)在任何樣式的庫(kù)中一起與 數(shù)據(jù)庫(kù)進(jìn)行通信。
1.8 JSONResponse 自定義返回
JSONResponse
可以設(shè)定回復(fù)內(nèi)容,JSONResponse可傳參數(shù):
- content: 響應(yīng)body內(nèi)容,str 或者 bytes.
- status_code: 響應(yīng)狀態(tài)碼,int類型,默認(rèn)200.
- headers: 響應(yīng)頭部,dict類型.
- media_type:media type. 例如"text/html".
- background:后臺(tái)任務(wù)
import uvicorn
from fastapi import FastAPI
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/")
def root():
return JSONResponse({"status":200}, status_code=405)
if __name__ == '__main__':
uvicorn.run(app, host="127.0.0.1", port=8080)
同時(shí)可以請(qǐng)求得到:
import requests
url = "http://127.0.0.1:8080"
response = requests.get(url)
response.json()
>>> {'status': 200}
筆者其實(shí)對(duì)這個(gè)status_code
比較好奇,在內(nèi)容反饋中,不會(huì)返回,而是通過(guò)curl請(qǐng)求得到的網(wǎng)頁(yè)狀態(tài)碼:
HTTP/1.1 405 OK
date: Tue, 18 Jul 2023 10:50:41 GMT
server: uvicorn
content-length: 36
content-type: application/json
{'status': 200}
1.9 router用法
參考:FastAPI APIRouter 的用法教程:深入解析使用
復(fù)雜開(kāi)發(fā)中,讓分支更加清晰可以使用router
@router.put(
prefix="/items",
tags=["custom"],
responses={403: {"description": "Operation forbidden"}},
)
一些參入?yún)?shù):
- prefix 參數(shù),路由的前綴
- tags 將應(yīng)用于特定路徑操作的內(nèi)容
- responses 指特定于該路徑下的響應(yīng)內(nèi)容,如上述便指定 404 的返回信息
請(qǐng)求的時(shí)候就是:0.0.0.0/items
進(jìn)行請(qǐng)求
來(lái)看一個(gè)例子,此處將三個(gè)文件進(jìn)行代碼統(tǒng)一放置:
# 路由器1.py
from fastapi import FastAPI, APIRouter
router = APIRouter()
@router.get("/")
async def hello():
return {"message": "Hello, FastAPI!"}
# 路由器2.py
from fastapi import FastAPI, APIRouter
router = APIRouter()
@router.get("/")
async def sayhi():
return {"message": "Hello, FastAPI!"}
# 二合一.py
from fastapi import FastAPI, APIRouter
from 路由器1.py import router as r1
from 路由器2.py import router as r2
app = FastAPI()
app.include_router(r1, prefix='/xxx', tags=['模塊一'])
app.include_router(r2, prefix='/xxx', tags=['模塊二'])
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
3 報(bào)錯(cuò)修復(fù)記錄
3.1 RuntimeError: asyncio.run() cannot be called from a running event loop
在jupyter notebook中運(yùn)行下述代碼就會(huì)出現(xiàn)上述報(bào)錯(cuò)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-653557.html
import uvicorn
from fastapi import FastAPI
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/")
def root():
return JSONResponse({"status":200}, status_code=405)
if __name__ == '__main__':
uvicorn.run(app, host="127.0.0.1", port=8080)
>>> RuntimeError: asyncio.run() cannot be called from a running event loop
這是jupyter notebook特有的,需要留意不要使用jupyter文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-653557.html
到了這里,關(guān)于FastAPI 構(gòu)建 API 高性能的 web 框架(二)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!