上一篇 FastAPI 构建 API 高性能的 web 框架(一)是把LLM模型使用Fastapi的一些例子,本篇简单来看一下FastAPI的一些细节。
有中文官方文档:fastapi中文文档
假如你想将应用程序部署到生产环境,你可能要执行以下操作:
pip install fastapi
并且安装uvicorn来作为服务器:
pip install "uvicorn[standard]"
然后对你想使用的每个可选依赖项也执行相同的操作。
1 基础使用
参考:https://fastapi.tiangolo.com/zh/tutorial/body-multiple-params/
1.1 单个值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]
代表参数q,可以是字符型也可以None不填,Query用来更多的补充信息,比如这个参数,默认值是None,最大长度50
1.2 多个参数
from typing import Annotated
from fastapi import FastAPI, Path
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
# 检查项,不同key要遵从什么格式
name: str
description: str | None = None # 字符或者None都可以,默认None
price: float
tax: float | None = None # 数值或者None都可以,默认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是一个路径,通过Annotated需要两次验证,验证一,是否是整数型,验证二,数值大小 大于等于0,小于等于1000
q: str | None = None,
item: Item | None = None, # 格式遵从class Item类且默认为None
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
if item:
results.update({"item": item})
return results
1.3 请求参数 Field
pydantic中比较常见
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比较相似,设置默认,title解释,最大长度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 响应模型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是控制输出的内容,按照规定的格式输出,作用概括为:
- 将输出数据转换为其声明的类型。
- 校验数据。
- 在 OpenAPI 的路径操作中为响应添加一个 JSON Schema。
- 并在自动生成文档系统中使用。
1.5 请求文件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 相比有更多优势:
- 这种方式更适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存;
- 可获取上传文件的元数据;
1.6 CORS(跨域资源共享)
https://fastapi.tiangolo.com/zh/tutorial/cors/
你可以在 FastAPI 应用中使用 CORSMiddleware 来配置它。
- 导入 CORSMiddleware。
- 创建一个允许的源列表(由字符串组成)。
- 将其作为「中间件」添加到你的 FastAPI 应用中。
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 - 一个允许跨域请求的源列表。例如 [‘https://example.org’, ‘https://www.example.org’]。你可以使用 [‘*’] 允许任何源。
1.7 与SQL 通信
https://fastapi.tiangolo.com/zh/tutorial/sql-databases/
FastAPI可与任何数据库在任何样式的库中一起与 数据库进行通信。
1.8 JSONResponse 自定义返回
JSONResponse
可以设定回复内容,JSONResponse可传参数:
- content: 响应body内容,str 或者 bytes.
- status_code: 响应状态码,int类型,默认200.
- headers: 响应头部,dict类型.
- media_type:media type. 例如"text/html".
- background:后台任务
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)
同时可以请求得到:
import requests
url = "http://127.0.0.1:8080"
response = requests.get(url)
response.json()
>>> {'status': 200}
笔者其实对这个status_code
比较好奇,在内容反馈中,不会返回,而是通过curl请求得到的网页状态码:
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 的用法教程:深入解析使用
复杂开发中,让分支更加清晰可以使用router
@router.put(
prefix="/items",
tags=["custom"],
responses={403: {"description": "Operation forbidden"}},
)
一些参入参数:
- prefix 参数,路由的前缀
- tags 将应用于特定路径操作的内容
- responses 指特定于该路径下的响应内容,如上述便指定 404 的返回信息
请求的时候就是:0.0.0.0/items
进行请求
来看一个例子,此处将三个文件进行代码统一放置:
# 路由器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 报错修复记录
3.1 RuntimeError: asyncio.run() cannot be called from a running event loop
在jupyter notebook中运行下述代码就会出现上述报错文章来源:https://www.toymoban.com/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文章来源地址https://www.toymoban.com/news/detail-653557.html
到了这里,关于FastAPI 构建 API 高性能的 web 框架(二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!