天下武功,唯快不破。在軟件開發中更是如此,“快”能從多方面提升用戶體驗。談到Python,它似乎天生就和速度無關,你可能很熟悉Django、Flask這些框架,雖然開發效率的確不錯,但是速度就一言難盡。那麼在前後端分離開發的時代,有沒有能拿得出手的Python Web框架呢?當然是有的,FastApi它來了。
一、為什麼是FastApi?
人們在介紹FastApi的時候通常會說“FastApi”是一個高性能的異步WEB框架。我相信沒有哪個程序員會跟“高性能”過不去,這往往也是我們所追求的東西。fastapi具有併發性能強、能夠快速上手、容錯能力強、自動生成交互式文檔的特點,這些都是我們選擇它的理由。
二、到底有多快?
很多人介紹FastApi框架時,經常說其併發性能能夠和NodeJS以及Go媲美,其實言過其實。在Go語言中文社區中夢想做小猿分別對Go、Flask、FastApi做了性能測試,迫於篇幅限制,我這裡直接放結果:
FastAPI:500併發 30秒:Speed=955466 pages/min, 238685 bytes/sec
Flask:500併發 30秒:Speed=33706 pages/min, 96457 bytes/sec
Go:500併發 30秒:Speed=116962 pages/min, 278740 bytes/sec
可見Go還是很強大的,但是fastapi已經遠遠超過了同為python框架的 flask。
與PHP7對比:
分別用PHP7、FastAPI從mongodb數據庫中取出相同的數據做成接口,相同參數得到相同的數據結果,速度如下:
FastApi用時43.06ms:
![性能是Flask的3倍!比PHP7還快!這個Python框架你值得擁有!](http://p2.ttnews.xyz/loading.gif)
PHP7 用時43.73ms:
![性能是Flask的3倍!比PHP7還快!這個Python框架你值得擁有!](http://p2.ttnews.xyz/loading.gif)
經過多次測試,成績較為穩定,無需取平均值,由此看來,FastApi速度上相比於其他Python框架,是佔有絕對優勢的!
三、安裝相關模塊
FaseApi這麼快,想必你已經迫不及待想要了解如何使用了。接下來我們講講如何開始第一個FastApi項目。
安裝FastApi執行 pip install fastapi
由於FastApi還需要一個ASGI服務框架 uvicorn,需要執行pip install uvicorn來安裝uvicorn。
注意Linux下一般會報錯如下:
Centos 執行yum install python3-devel,Ubuntu 執行sudo apt-get install python3-dev,即可解決問題,非常簡單!
四、Hello, API
現在就來快速上手吧:
第一個api:
創建文件zhiliao.py,碼代碼:
<code>from
fastapiimport
FastAPI app = FastAPI()def
read_root
()
:return
{"Hello"
:"Api"
}/<code>
然後在zhiliao.py文件所在目錄,執行uvicorn zhiliao:app --reload
其中,zhiliao是py文件名,冒號後面的app是我們在代碼中創建的FastAPI實例,這一點類似Flask,其他參數等下會詳細說到。
執行之後,得到反饋信息。
可以看到Uvicorn running on [http://127.0.0.1:8000 [0m (Press CTRL+C to quit),打開瀏覽器:
這樣就成功的創建了第一個接口服務,每次請求的同時我們也能能夠看到,請求日誌,方便調試。
獲取路徑參數:
接著寫如下代碼:
<code> @app.get("/hello/{name}"
)def
hello
(name)
: res = {} res['name'
] = namereturn
res/<code>
保存之後可以看到:
項目自動重新加載了,我們無需再執行uvicorn……,原因是我們剛剛啟動實例時,加了--reload參數,這一點類似於Flask中的debug=True,不推薦在線上環境中開啟,僅為了線下調試方便。
訪問瀏覽器:
http://127.0.0.1:8000/hello/知了,可以看到:
我們不難發現,res在程序中是一個字典,而fastapi將其自動轉為了json格式,無需再使用json模塊進行編碼,這極大的便利了我們的開發。
問號傳參與數據類型限制:
為了防止用戶填寫表單時不按套路來,我們最好對參數類型進行限制,上代碼:
<code>@app.get("/zhiliao"
)def
read_args
(
name:
str,age:
int):return
{"name"
: name,"age"
:age
}/<code>
瀏覽器訪問
http://127.0.0.1:8000/zhiliao?name=張三&age=23:
如果改成
http://127.0.0.1:8000/zhiliao?name=張三&age='23'也即是字符23,會報錯,提示數據類型錯誤。
<code>{"detail"
:[{"loc"
:["query"
,"age"
],"msg"
:"value is not a valid integer"
,"type"
:"type_error.integer"
}]}/<code>
自動生成文檔:
fastapi具有自動生成文檔的能力:
交互文檔:
訪問:
http://127.0.0.1:8000/docs,可以看到,上面我們寫的三個接口都已經給出了文檔。
還可以繼續用於測試,我們測試一下第三個接口,填寫兩個值,然後點擊 execute:
可以看到,給出了非常詳細的反饋信息:
API文檔:
我們打開
http://127.0.0.1:8000/redoc
可以看到詳細的文檔:
五、進階篇:
1. 基礎參數配置:
我們使用uvicorn 配合fastapi,它是一個基於 asyncio 開發的一個輕量級高效的 Web 服務器框架。
下面一條命令演示常用參數:
<code>uvicorn
zhiliao
:app
--host
127.0
.0
.1
--port
80/<code>
--host是綁定的地址,127.0.0.1為本地,如果是0.0.0.0,那麼意味著它將暴露在公網中,所有人都可以訪問,線上環境常用。
--port 80表示,使用80端口作為該服務的默認端口,無需在地址後加端口號,可以直接訪問 http://127.0.0.1
2. 開啟 HTTPS, 給你的網站加把小鎖:
鮮有人在講fastapi時提到開啟HTTPS,大人,時代變了,http早已經被谷歌瀏覽器標記為不安全。不過,你還別說,網站上了https 還真是好看呢。
另外,如果我們的應用不開啟https,那麼將意味著只能被未開啟ssl的網站調用,假設我們主站用的是https,那麼我們必須開啟HTTPS,否則會調用失敗。
說了這麼多,其實做起來很簡單,執行uvicorn --help可以看到詳細的配置文檔,可以看到:
<code> [default:2
]/<code>
有這麼三個參數,第一個是證書的key文件,第二個是crt文件,第三個不用管是默認的。
只需執行:
<code>uvicorn
zhiliao:app
--host
0.0
.0
.0
--port
8080
--ssl-keyfile
/ssl/private.key
--ssl-certfile
/ssl/certificate.crt
/<code>
這意味著我們的應用將會在8080端口運行,並且暴露在公網中,人們都可以訪問,--ssl-keyfile參數後面跟key文件目錄,--ssl-certfile,同理。可以看到,網站已經可以用https訪問。
3. 配置跨域傳參
既然是接口服務,那麼跨域傳參是必然要碰到的問題。
現有情景如下我們的Api服務是127.0.0.0:8000,而我們的網站主域名是127.0.0.1,
不同端口屬於不同域,下面的介紹也適合其他跨域場景比如主站是www.xx.com而api服務的域名是api.xx.com,同樣適合。
現在網站要調用api的接口,我們用jquery的 ajax試一下:
建立一個測試文件zhiliao.html,寫入如下內容並訪問:
<code><
script
src
="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"
>script
><
script
>$.
get
("http://127.0.0.1:8000/", function(data){console
.log(data); });script
>/<code>
可以看到,由於是不同域,訪問失敗:
加上幾行代碼,最終如下:
<code>from
fastapiimport
FastAPIfrom
starlette.middleware.corsimport
CORSMiddleware app = FastAPI() origins = ["http://127.0.0.1"
] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True
, allow_methods=["*"
], allow_headers=["*"
])def
read_root
()
:return
{"Hello"
:"Api"
}def
hello
(name)
: res = {} res['name'
] = namereturn
resdef
read_args
(name:str, age:int)
:return
{"name"
: name,"age"
:age }/<code>
我們刷新瀏覽器:
跨域傳參成功,獲取數據成功。
那麼,介紹到這裡就結束了,相信有了python+fastapi的加持,python在web領域又多了一席之地。也希望,fastapi成為你的得力工具。