1.介紹
前言: 不管學(xué)什么語言谆吴,都應(yīng)該至少掌握一個框架些侍,方面我們后續(xù),進(jìn)行服務(wù)部署龙屉、服務(wù)對外支持等;
1.1 官網(wǎng)介紹
下面是來自FastAPI
官網(wǎng)的介紹:
FastAPI
是一個用于構(gòu)建 API
的現(xiàn)代呐粘、快速(高性能)的 web
框架,使用 Python 3.8+
并基于標(biāo)準(zhǔn)的 Python
類型提示转捕。
關(guān)鍵特性:
-
快速:可與 NodeJS 和 Go 并肩的極高性能(歸功于
Starlette 和 Pydantic
)作岖。最快的 Python web 框架之一。 - 高效編碼:提高功能開發(fā)速度約 200% 至 300%五芝。
- 更少 bug:減少約 40% 的人為(開發(fā)者)導(dǎo)致錯誤痘儡。
- 智能:極佳的編輯器支持。處處皆可自動補(bǔ)全枢步,減少調(diào)試時間沉删。
- 簡單:設(shè)計的易于使用和學(xué)習(xí),閱讀文檔的時間更短醉途。
- 簡短:使代碼重復(fù)最小化矾瑰。通過不同的參數(shù)聲明實(shí)現(xiàn)豐富功能。bug 更少隘擎。
- 健壯:生產(chǎn)可用級別的代碼殴穴。還有自動生成的交互式文檔。
-
標(biāo)準(zhǔn)化:基于(并完全兼容)API 的相關(guān)開放標(biāo)準(zhǔn):OpenAPI (以前被稱為
Swagger
) 和 JSON Schema货葬。 - 官方文檔:https://fastapi.tiangolo.com/zh/
1.2 Github熱度
框架 | Star |
開源地址 |
---|---|---|
django |
77.6k |
https://github.com/django/django |
flask |
66.8K |
https://github.com/pallets/flask |
fastapi |
72.6K |
https://github.com/tiangolo/fastapi |
關(guān)于選框架一事,每個人的見解都不一樣,這里不做比較,簡單陳述下,我之所以選擇這個框架的原因:
- 號稱和
Go
并肩的極高性能; - 框架和之前兩個對比,相對比較年輕,從
Github star
數(shù)來看采幌,成長熱度挺好; - 官方文檔中文支持較好,看著也比較完善震桶;
2.依賴安裝
@注意: fastapi有版本要求植榕,需要的
Python
版本至少是Python 3.8
2.1 安裝fastapi
# 使用pip安裝
$ pip install fastapi
2.2 安裝ASGI 服務(wù)器
ASGI
是異步網(wǎng)關(guān)協(xié)議接口,一個介于網(wǎng)絡(luò)協(xié)議服務(wù)和Python
應(yīng)用之間的標(biāo)準(zhǔn)接口尼夺,能夠處理多種通用的協(xié)議類型,包括HTTP炒瘸,HTTP2
和WebSocket
淤堵。
pip install "uvicorn[standard]"
這里簡單了解下什么是uvicorn
:
Uvicorn
是一個基于ASGI(Asynchronous Server Gateway Interface)
的異步Web
服務(wù)器,用于運(yùn)行異步Python web
應(yīng)用程序顷扩。它是由編寫FastAPI
框架的開發(fā)者設(shè)計的拐邪,旨在提供高性能和低延遲的Web
服務(wù);
3. 快速啟動
3.1 編寫代碼
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def index():
"""
注冊一個根路徑
:return:
"""
return {"message": "Hello World"}
@app.get("/info")
async def info():
"""
項目信息
:return:
"""
return {
"app_name": "FastAPI框架學(xué)習(xí)",
"app_version": "v0.0.1"
}
3.2 啟動服務(wù)
(py310) PS D:\wwwroot\python\test> uvicorn main:app --reload
INFO: Will watch for changes in these directories: ['D:\\wwwroot\\python\\test']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [25532] using WatchFiles
INFO: Started server process [9960]
INFO: Waiting for application startup.
INFO: Application startup complete.
啟動命令uvicorn main:app --reload中的app,指的是app = FastAPI()變量隘截,也可以是其他自己定義的名稱;
1.啟動步驟分析:
- 第一步: 導(dǎo)入
FastAPI
(from fastapi import FastAPI
),可以把FastAPI
理解為是API
提供所有功能的Python
類; - 第二步: 創(chuàng)建
FastAPI
實(shí)例(app = FastAPI()
),實(shí)例化一個類,變量app
是FastAPI
的類實(shí)例扎阶; - 第三步: 使用
@app.get
注冊路由,其中app
是FastAPI
類實(shí)例變量名汹胃,也可以是其他;除了@app.get
之外還支持:@app.post东臀、@app.put着饥、@app.delete..
等方法; - 第四步: 使用
uvicorn
啟動服務(wù)惰赋;
3.3 調(diào)試模式
雖然通過uvicorn
啟動服務(wù)很方便宰掉,但有時候我們需要debug
本地程序,方便問題排查,FastAPI
也支持傳統(tǒng)啟動方式;修改main.py
文件赁濒,追加以下代碼:
...
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
以Debug
模式啟動后轨奄,就可以打斷點(diǎn)進(jìn)行代碼調(diào)試,具體使用方法可參考官方文檔:https://fastapi.tiangolo.com/zh/tutorial/debugging
4.訪問服務(wù)
4.1 訪問接口
4.2 訪問文檔
FastApi
框架在啟動時,除了注冊路由之外拒炎,還會自動生成API
在線文檔,并且生成兩種在線文檔: Swagger UI 和 ReDoc挪拟,訪問地址分別為:
-
SwaggerUi風(fēng)格文檔:
http://127.0.0.1:8000/docs -
ReDoc風(fēng)格文檔:
http://127.0.0.1:8000/redoc
文檔
1.如何關(guān)閉文檔生成?
如果不想生成交互式文檔,可以通過以下方式實(shí)例化FastAPI
:
# docs_url=None: 代表關(guān)閉SwaggerUi
# redoc_url=None: 代表關(guān)閉redoc文檔
app = FastAPI(docs_url=None, redoc_url=None)
4.3 訪問OpenAPI
FastAPI
框架內(nèi)部實(shí)現(xiàn)了OpenAPI
規(guī)范,通過訪問 http://127.0.0.1:8000/openapi.json,我們可以看到整個項目的 API
對應(yīng)的JSON
描述信息,如下:
{
"openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/": {
"get": {
"summary": "Index",
"description": "注冊一個根路徑\n:return:",
"operationId": "index__get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {}
}
}
}
}
}
},
"/info": {
"get": {
"summary": "Info",
"description": "項目信息\n:return:",
"operationId": "info_info_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {}
}
}
}
}
}
}
}
}
5.目錄結(jié)構(gòu)
5.1 官方示例目錄結(jié)構(gòu)
通常我們開發(fā)一個Python
服務(wù)击你,都不會將所有代碼放到一個文件里玉组,就像我們不會把衣服、鞋子果漾、襪子球切、食物這些統(tǒng)統(tǒng)裝到一個麻袋里一樣; 而是會根據(jù)功能或者其他規(guī)則,分類存放绒障,FastAPI
為我們提供了一個模板吨凑,具體如下:
├── app # 「app」是一個 Python 包
│ ├── __init__.py # 這個文件使「app」成為一個 Python 包
│ ├── main.py # 「main」模塊,例如 import app.main
│ ├── dependencies.py # 「dependencies」模塊户辱,例如 import app.dependencies
│ └── routers # 「routers」是一個「Python 子包」
│ │ ├── __init__.py # 使「routers」成為一個「Python 子包」
│ │ ├── items.py # 「items」子模塊鸵钝,例如 import app.routers.items
│ │ └── users.py # 「users」子模塊,例如 import app.routers.users
│ └── internal # 「internal」是一個「Python 子包」
│ ├── __init__.py # 使「internal」成為一個「Python 子包」
│ └── admin.py # 「admin」子模塊庐镐,例如 import app.internal.admin
具體代碼組織可以參考 更大的應(yīng)用 - 多個文件: https://fastapi.tiangolo.com/zh/tutorial/bigger-applications/
5.2 自定義目錄結(jié)構(gòu)
個人感覺官方推薦的目錄結(jié)構(gòu)過于簡單恩商,和工作中經(jīng)常使用的其他語言框架目錄結(jié)構(gòu)出入過大,所以進(jìn)行了自定義修改必逆,也是為了適應(yīng)自己的開發(fā)習(xí)慣怠堪,具體修改后目錄如下:
├── README.md #項目介紹
├── app
│ ├── __init__.py
│ ├── config # 配置相關(guān)
│ │ └── __init__.py
│ ├── constant # 常量相關(guān)
│ │ └── __init__.py
│ ├── dao # 封裝查詢數(shù)據(jù)的方法
│ │ └── __init__.py
│ ├── dependencies # 封裝被依賴函數(shù)
│ │ └── __init__.py
│ ├── middleware # 中間件
│ │ └── __init__.py
│ ├── models # 數(shù)據(jù)模型文件,和表結(jié)構(gòu)對應(yīng)
│ │ └── __init__.py
│ ├── router # 路由也可以理解controller
│ │ ├── __init__.py
│ │ ├── default_router.py # 默認(rèn)接口
│ │ └── demo_router.py # 演示接口
│ ├── parameter # 聲明參數(shù)對應(yīng)的Pydantic模型
│ │ └── __init__.py
│ ├── service # 就具體業(yè)務(wù)實(shí)現(xiàn)邏輯
│ │ └── __init__.py
│ └── utils # 工具類
│ ├── __init__.py
│ └── str_util.py
├── main.py # 主文件
├── requirements.txt #依賴文件
├── tests # 單元測試目錄
├── __init__.py
└── local_test.py
a.__init__.py
文件的作用:
-
標(biāo)識包目錄: 當(dāng)Python解釋器遇到一個目錄中包含
__init__.py
文件時名眉,它會將該目錄識別為一個包粟矿。這樣可以通過導(dǎo)入包的方式來組織和訪問模塊。在Python3
中损拢,__init__.py
不再是創(chuàng)建包的唯一方式 -
初始化包:
__init__.py
文件在包被導(dǎo)入時會被執(zhí)行陌粹,可以用于初始化包級別的變量、設(shè)置環(huán)境或執(zhí)行其他必要的初始化操作福压。 -
命名空間包含: 通過在
__init__.py
中定義變量掏秩、函數(shù)或類或舞,可以將它們添加到包的命名空間中,使得在導(dǎo)入包時可以直接訪問這些元素蒙幻。 -
避免名稱沖突: 如果包目錄中有與包同名的模塊映凳,導(dǎo)入包時可能會出現(xiàn)沖突。
__init__.py
可以通過定義__all__
變量來控制導(dǎo)入時的名稱空間杆煞。
# __init__.py
__all__ = ['module1', 'module2']
這樣導(dǎo)入包時魏宽,只有在 __all__
中列出的模塊會被導(dǎo)入,避免了潛在的名稱沖突
6. 路由加載
6.1 路由文件
假如我們在app/router
目錄下有以下幾個文件:
? tree -L 2 app/router -I "__pycache__"
app/router
├── __init__.py
├── default_router.py
└── demo_router.py
每個路由文件里面的編輯流程和邏輯基本一樣决乎,這里以default_router.py
為例队询,代碼如下:
# 導(dǎo)入APIRouter
from fastapi import APIRouter
# 實(shí)例化APIRouter實(shí)例
router = APIRouter(tags=["默認(rèn)路由"])
# 注冊具體方法
@router.get("/")
async def index():
"""
默認(rèn)訪問鏈接
"""
return {
"code": 200,
"msg": "Hello World!"
}
6.2 官方加載示例
文檔地址: https://fastapi.tiangolo.com/zh/tutorial/bigger-applications/#fastapi
在主體文件main.py
中,代碼如下:
from fastapi import Depends, FastAPI
...
# 從routers導(dǎo)出路由文件:items, users
from .routers import items, users
# 挨個注冊文件
app.include_router(users.router)
app.include_router(items.router)
app.include_router(
admin.router,
prefix="/admin",
tags=["admin"],
dependencies=[Depends(get_token_header)],
responses={418: {"description": "I'm a teapot"}},
)
@app.get("/")
async def root():
return {"message": "Hello Bigger Applications!"}
6.3 優(yōu)化導(dǎo)入
1.編輯app/router/__init__.py
from app.router import default_router, demo_router
# 定義路由列表
RegisterRouterList = [
default_router,
demo_router
]
在__init__.py
中定義變量,把要注冊的路由統(tǒng)一放在列表中,然在main.py
中通過循環(huán)加載路由构诚;后續(xù)有新增路由時,直接在列表中新增元素即可蚌斩;
2.修改main.py
import uvicorn
from fastapi import FastAPI
from app.router import RegisterRouterList
# 實(shí)例化
app = FastAPI()
# 加載路由
for item in RegisterRouterList:
app.include_router(item.router)
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)