
node.js + express + docker + mysql + jwt 實現用戶管理restful api
這是國外一個專門做框架性能對比的網站(TechEmpower)的數據,這是對 Python 語言的常用 web 框架的測試報告,可見 fastapi 表現優異。
這是詳細的鏈接,有興趣的可以看下:
除了在上邊數據方面的優異表現外,它還具有如下特點:
拋去這些,我覺著僅性能堪比 Golang 語言的 gin 框架這一條,就值得我們學習下。
下面我們來具體看下 FastApi 的使用。
在看 FastApi 之前,我們先來回憶下 Python 的異步編程和協程。
Python 1.0 發布在 1994 年,當時對編程語言性能的要求并不像現在這么高,所以它在設計之初就更傾向于快速開發和便捷的語法。即便有性能的要求,多進程多線程也完全能夠應付。但是隨著現代互聯網的發展,對編程語言自身的性能要求就越來越高。除了多進程和多線程模型,還逐漸演化出「協程」模型(協程,是一種用戶態的更小力度的任務運行單元?;诰€程,可實現多個任務的并行。)為代表的異步編程思想。
在早期,Python 實現異步編程,需要地方的庫,如 Twisted、Tornado 等。從 Python3 開始,加入了對異步編程的原生支持。
yield from
,用戶可實現基于生成器的簡易協程;asyncio
庫,正式引入協程概念,使用關鍵字@asyncio.coroutine
和yield from
來表示協程調用;async/await
代替@asyncio.coroutine
和yield from
,可以讓我們使用同步的方式寫出異步的代碼;下面這種以async def
定義函數,且用await
?關鍵字來調用函數的代碼,便是協程相關的代碼。
import asyncio
async def compute(x, y):
print("Compute %s + %s ..." % (x, y))
await asyncio.sleep(1.0)
return x + y
async def print_sum(x, y):
result = await compute(x, y)
print("%s + %s = %s" % (x, y, result))
loop = asyncio.get_event_loop()
loop.run_until_complete(print_sum(1, 2))
loop.close()
協程的運行有 3 種方式,參考[5]
aysncio.run()
用來運行最高層次的main()
函數;await
調用協程函數;asyncio.create_task()
并發運行作為asyncio
任務的多個協程;一些其他概念:
CGI(通用網關接口, Common Gateway Interface),簡單來說就是解析瀏覽器等客戶端發送給服務端的請求,并組裝需要返回的 HTTP 請求的一種通用協議,處理這個過程的程序,我們就可以叫 CGI 腳本。互聯網早起的動態網頁都是基于 CGI 標準的。
WSGI?是一種 Python 專用的 Web 服務器網關接口,它分為兩部分”服務器(或網關)“和”應用程序(或應用框架)”。「服務器」,一般獨立于應用框架,為應用程序運行提供環境信息和一個回調函數(Callback Function)。當應用程序完成處理請求后,透過回調函數,將結果回傳給服務器。常用的 WSGI 服務器有: uwsgi、gunicon?!笐贸绦颉?,是各種實現了 WSGI 標準的 Python web 框架了,常用的有 Django、Flask 等。
ASGI(Asynchronous Server Gateway Interface)?是 Django 團隊提出的一種具有異步功能的 Python web 服務器網關接口協議。能夠處理多種通用的協議類型,包括 HTTP,HTTP2 和 WebSocket。WSGI 是基于 HTTP 協議模式的,不支持 WebSocket,而 ASGI 的誕生則是為了解決 Python 常用的 WSGI 不支持當前 Web 開發中的一些新的協議標準(WebSocket、Http2 等)。同時,ASGI 向下兼容 WSGI 標準,可以通過一些方法跑 WSGI 的應用程序。常用的「服務器」有 Daphne、Uvicorn。
FastApi 要求 Python 在 3.6 以上,它應用了很多 Python3 的新特性。下面我們安裝一下:
pip install fastapi uvicorn
我們使用uvicorn
來啟動異步的 web server ,同時把uvicorn
也安裝上。
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
uvicorn main:app --reload
,生產推薦,生產中把 reload 去掉。python main.py
,僅用于調試。if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
整體代碼看下來,和 Flask 的 Hellow world 類似,有程序實例 app 用來啟動程序,有路由和路由處理函數。
我們來看下它自帶的 Swagger 類型的文檔:
是不是很方便。
接下來,讓我們來看些復雜點的用法。
使用 get 方法來請求數據:
@app.get('/user')
async def user(user_id: int = Query(..., title="The ID of the user to get", gt=0)):
# do somethings
return {'user_id': user_id}
QueryString 的傳遞使用了一個類Query
來做參數的校驗,Query 類繼承了相關 pydandic 庫的類,實現了對參數的類型校驗,附默認值等功能。
此處...
是表示 user_id 參數時必須的。若此處為 None,則表示 user_id 可選。
使用 put 方法來更新數據:
@app.put('/user/{user_id}')
async def user(user_id: int = Path(..., title="The ID of the user to get", gt=0)):
# do somethings
return {'user_id': user_id}
這里的路徑參數,可以使用類Path
來做類型校驗,功能和Query
類似。
使用 post 方法來創建數據:
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
@app.post("/users/")
async def create_user(user: User):
# do somethings
return user
這里定義了一個用戶類,作為函數參數的類型。在請求時,FastApi 會自動的將參數注入到該類型的各對應屬性字段。該類也起到了參數類型校驗的作用。在函數參數類型這塊,User
類有點類似 Golang 中結構體定義的函數參數類型。
使用 delete 方法來刪除數據:
@app.delete('/user/{user_id}')
async def user(user_id: int = Path(..., title="The ID of the user to get", gt=0)):
# do somethings
return {'user_id': user_id}
同 put 方法的用法。
看了這些基本的用法之后,我們對 FastApi 的使用有了一個初步的了解。
我們從之前的代碼中可以看到路由和路由函數在一塊的,這種方式在路由少的情況下是非常方便的,但是隨著項目復雜度的提升,路由逐漸增多,如果路由設計不合理,便會非常的不好維護。
針對這種情況,FastApi 提供了 APIRouter
類來規劃設計路由,以便適應大型的項目架構。
APIRouter
?類的基本用法如下:
# 頁面路由
page_routes = APIRouter()
page_routes.include_router(views.router, prefix="")
# api 相關路由
api_routes = APIRouter()
api_routes.include_router(api_v1_views.router, prefix='/v1')
api_routes.include_router(api_v2_views.router, prefix='/v2')
可以通過它來拆分管理路由,最后再將所有路由注冊到根路由即可。
app = FastAPI()
app.include_router(page_routes)
app.include_router(api_routes, prefix=config.API_PREFIX)
接下來,讓我們看一個真實的生產環境中的項目案例:
我們從下邊幾點來詳細說下這個項目案例:
首先在 ORM 選擇方面,官方推薦了強大的SQLAlchemy
,它可以說是 Python web 開發中最好用的第三方 ORM 了。在同步框架 Flask 中,應該說已經成為標配。
SQLAlchemy
目前為止對異步的支持還不夠完成,官方推薦使用 Encode 組織下的異步驅動 databases
(目前支持 PostgreSQL/MySQL/SQLite),只所以叫他驅動沒叫他 ORM,是因為它僅提供了和數據庫的異步鏈接的管理,并沒有對象模型。在使用的時候,可以結合SQLAlchemy
或直接寫 SQL。
使用SQLAlchemy
來處理同步的數據操作,使用SQLAlchemy
加databases
來實現異步的數據操作,完美實現了我們的需求。
SQLAlchemy
還有一個數據庫遷移的問題,它自己不支持數據庫表的變更遷移,只能刪除重建。在 Flask 中可以使用插件flask_migrate
來實現數據庫表的變更遷移。
SQLAlchemy
官方推薦使用alembic
。一個遷移過程大概步驟如下:
# 1/ 初始化環境
alembic init migrations
# 2/ 修改配置參數
# migrations/env.py
import sys
sys.path = ['', '..'] + sys.path[1:]
from core.config import DATABASE_URL
config.set_main_option("sqlalchemy.url", str(DATABASE_URL))
...
from models.posts import PostsBase
from models.posts2 import PostsBase2
target_metadata = Base.metadata # 一個app model
target_metadata = [PostsBase.metadata, PostBase2.metadata] # 多個app model
# 3/ 生成遷移腳本
alembic revision --autogenerate -m "init"
# 4/ 應用遷移腳本到數據庫
alembic upgrade head
從項目目錄可以看到有個 service 目錄,很顯然,當業務邏輯服務度升高時,我們可以提取很多共用的邏輯作為底層的共用邏輯。這個就比較靈活了,完全有你自己控制。各種設計模式,就可以往上懟了。
最后我們來看下 docker 化,Dockerfile 如下:
# 我們選擇了官方 slim 鏡像,體積相對小
FROM python:3.9-slim-buster
LABEL maintainer="DeanWu <pyli.xm@gmail.com>"
# stdout 無緩沖,直接輸出
ENV PYTHONUNBUFFERED 1
# 復制代碼,調整工作目錄和腳本權限
COPY . /app
WORKDIR /app
RUN chmod +x start.sh prestart.sh start-reload.sh
# 安裝用到的工具和python 包
RUN apt-get update && \
apt-get install -y --no-install-recommends default-libmysqlclient-dev gcc libffi-dev make && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
pip install --no-cache-dir -r requirements.txt && \
rm -rf requirements.txt && \
pip install --no-cache-dir gunicorn
ENV PYTHONPATH=/app
EXPOSE 80
# 啟動命令 可添加也可不添加
#CMD ["sh", "start.sh"]
編譯和啟動,
docker build -t fastapi-mysql:v1.0 .
docker run -p 80:80 -d -e DB_CONNECTION="mysql://root:Root1024@xxxx/fastapi" fastapi-mysql:v1.0 ./start.sh
到這里我們從背景到生產項目案例,已經介紹完FastApi
?這個框架了,你有沒有覺著這個框架很酷呢?我今天只是簡單的介紹了框架的部分應用場景,還有很多好玩的功能,大家可以去參考它的官方文檔。也可以關注我公眾號,一起討論學習。
本文章轉載微信公眾號@碼農吳先生
node.js + express + docker + mysql + jwt 實現用戶管理restful api
nodejs + mongodb 編寫 restful 風格博客 api
表格插件wpDataTables-將 WordPress 表與 Google Sheets API 連接
手把手教你用Python和Flask創建REST API
使用 Django 和 Django REST 框架構建 RESTful API:實現 CRUD 操作
ASP.NET Web API快速入門介紹
2024年在線市場平臺的11大最佳支付解決方案
完整指南:如何在應用程序中集成和使用ChatGPT API
選擇AI API的指南:ChatGPT、Gemini或Claude,哪一個最適合你?