快速上手,簡單易懂:Python新手的FastAPI之旅

Sean Yeh
Python Everywhere -from Beginner to Advanced
15 min readJun 26, 2023
Königsallee, Düsseldorf, Deutschland , photo by Sean Yeh

您聽過FastAPI嗎?

FastAPI是在Python中構建RESTful API的現代Web框架,於2018年首次發布。在Python眾多的框架中,FastAPI雖然名氣可能還不如Flask或Django那麼大,但卻有著自己獨特的魅力:它的執行速度超快、使用起來簡單直覺,而且還能自動產生API文件,讓你的開發過程變得輕鬆愉快。

如果您對於剛剛提到的這些特點感到好奇的話,那就讓我們一起展開這次的FastAPI新手之旅吧!

在接下來的文章中,將為大家介紹FastAPI的主要特性,並分享如何快速上手使用FastAPI。

此外,我們還會看一些FastAPI實際的應用案例。無論你是剛接觸Python程式的新手,還是想在Python的學習中尋找新的可能,相信這篇文章都能給你帶來新的啟示。

那麼,讓我們一起踏上這趟旅程,進入FastAPI的世界吧!

FastAPI的特性與優勢

那麼,FastAPI到底有什麼讓人無法忽視的特性與優勢呢?

速度

首先,最吸引人的莫過於它的速度。如同它的名字FastAPI,「快」是它的招牌。根據多項性能測試顯示,FastAPI是目前所有Python框架中最快的。對於那些在意效能,或者是在伺服器負載上有所考量的開發者來說,這無疑是一大利多。

易用

接著是它的易用性。FastAPI使用OpenAPI的開源標準,還有auto complete,讓你的開發過程更加流暢無阻。對於初學者來說,這個特性無疑讓學習曲線降低了許多。

文件

還有一點讓人讚不絕口的是FastAPI會自動產生對應的API文件。寫完API之後,只需要一個簡單的指令,FastAPI就會幫你生成所有相關的API文件,無需再花費額外的時間與精神去管理文件,是不是超省事?

簡潔

最後,對於曾有過Python應用程式開發經驗的朋友們,FastAPI的簡潔語法會讓您感到非常親切。與Flask、Django等其他Python框架相比,FastAPI的語法更為直覺且易懂,並且能夠支援現代的非同步處理模型,對於想嘗試新框架的您來說,轉換框架的學習成本並不高。

總結起來,FastAPI以其快速、直覺的開發體驗、自動產生文件以及簡潔的語法,在Python網頁框架中嶄露頭角。不論你是初學者還是有經驗的開發者,都值得嘗試FastAPI。

快速上手FastAPI

廢話不多說,我們直接進入實際操作,看看如何快速上手FastAPI。

首先,按照慣例,我們需要安裝FastAPI。如果您已經安裝了Python和pip,那麼只需在命令列中輸入以下指令即可:

pip install fastapi

接著我們還需要一個ASGI伺服器,這裡我們使用uvicorn。您可以用透過下面的指令來安裝:

pip install uvicorn

註:以上的安裝,強烈建議在安裝前先建立一個虛擬環境。並在虛擬環境下安裝各個套件。

安裝完成後,我們就可以開始編寫第一個FastAPI應用程式了。打開您的程式編輯器(例如VS Code),並且建立一個新的Python檔案,例如 main.py,然後在新建立的檔案中輸入以下程式碼:

# main.py

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
return {"Hello": "FastAPI"}

以上的程式碼,將會建立了一個極簡的FastAPI應用程式(眼前所見一切複雜的事務,都從最簡單的地方開始)。當您啟動伺服器並且透過網頁瀏覽器瀏覽應用程式的根目錄網址( / )時,程式會回傳一個JSON格式的回應,其內容為 {“Hello”: “FastAPI”}

若要執行這個應用程式,我們需要使用uvicorn來啟動伺服器。回到你的命令列介面,輸入以下指令即可:

uvicorn main:app --reload

這裡的「main」應該是您的Python檔案的名稱,而「app」則是我們在檔案中建立的FastAPI實例的名稱( 也就是 app = FastAPI() 的app)。「 — reload」選項使得當您修改程式碼時,伺服器會自動重新載入,非常適合開發時使用。

輸入指令後,按下enter啟動(終端機會顯示下面訊息)。

恭喜!您的第一個FastAPI應用程式已經成功運行了!可以在瀏覽器中輸入http://127.0.0.1:8000 或者是 http://localhost:8000,就可以看到您的應用程式。

看起來是不是很簡單?FastAPI的設計理念就是讓你輕鬆上手,快速開發。接下來,您可以試著新增更多路由,定義更多函式,讓您的應用程式更加豐富多樣。

FastAPI的GET應用

GET應用可以分為三種類型來討論。

  • 路徑參數(Path parameters)
  • 預定義值Predefined values
  • 查詢參數Query parameters

以下分別針對各種類型說明其使用方式。

路徑參數 Path Parameters

路徑參數(Path parameters)也稱為 URL 參數,它是一個參數,這個參數讓我們可以嵌入在 URL 路徑中使用。

例如,在 URL /items/{item_id} 中,item_id 是一個路徑參數。你可以在 FastAPI 應用程式的路由函式中使用相同的名稱作為參數來接收這個值。

例如我們在前面的main.py裡面增加下面這一段程式碼:

@app.get("/blog/{id}")
def get_blog(id):
return {"data":f"Blog 的 id 是:{id}"}

在程式碼中,我們設定了一個路徑參數id。如果在網頁中輸入下面的路徑「

http://127.0.0.1:8000/blog/5」就會得到下面的結果:

#判斷路徑參數的型態

如果希望使用者輸入的路徑參數id只限於特定的資料型態的話,應該如何處理?以上面的例子來說,假設我只希望使用者輸入數字作為路徑參數,其他型態的參數都一蓋不接受,我們可以這樣子處理:

@app.get("/blog/{id}")
def get_blog(id: int):
return {"data": f"Blog 的 id 是:{id}"}

由於我們在id的後面加上int( id: int ),程式會對輸入的參數id 進行判斷。int 代表的是實數。換句話說,如果id不是實數的話,就會出現錯誤訊息。例如我們在網址列輸入「http://127.0.0.1:8000/blog/fun」,會得到下面的結果。

#路由函式的順序很重要

當我們有一個函式,該放在哪個位置比較適當,需要謹慎決定。以下面的例子來說,假設我們有ㄧ個如下的函式get_blogs_all,到底應該放在哪裡比較好?也就是說函式 index 、get_blogs 與get_blogs_all三者應該如何排列?

@app.get("/blog/all")
def get_blogs_all():
return {"message": "所有的 blogs"}

如果以下面方式排序,會出現錯誤,是不可行的順序方式:

即使輸入http://127.0.0.1:8000/http://127.0.0.1:8000/blog/5 都會得到正確的結果,但是當我們輸入 http://127.0.0.1:8000/blog/all 時,就會得到錯誤的結果。因為在順序上路由函式get_blog在get_blogs_all的前面,在原則上會先執行第14行的函式,後再執行第19行的函式。

若將三個函式調整為以下的順序,就可以正常執行:

在這樣的狀況下,輸入 http://127.0.0.1:8000/blog/all 就不會出現錯誤。因為原本第14行的函式被移到第19行的位置。get_blogs_all就可以被執行。也就是blog/all的條件可以被滿足。

預定義值Predefined values

這種特性允許你為路徑參數或查詢參數設置預定義的有效值。當使用者端發送的請求中,其請求的參數值不在你的預先定義值之中時,FastAPI 會自動回傳一個錯誤,告訴客戶端哪些值是被接受的。

要使用這個功能,首先需要匯入Enum,並且透過Enum(列舉)設定一個class。藉由這個class來定義我們需要的預定值。以下舉例說明:

下面的BlogType class,繼承了Enum,並定義了我們需要的三個預定值。

class BlogType(str, Enum):
business = "business"
story = "story"
qa = "qa"

由上面程式碼可以看到,裏面總共定義了三種有效值:business、story、qa。接著,就像前面我們在判斷路徑參數的型態時使用的方式一樣,在路徑函式get_blog_type裡面設定type的判斷為BlogType class。

@app.get("/blog/type/{type}")
def get_blog_type(type: BlogType):
return {"message":f"Blog 的資料型態是 {type}"}

使用者輸入BlogType裡面的任何一個值,都是有效的,get_blog_type函式會被執行:

反之,如果使用者的請求超過business、story、qa這三個有效值,就會出現錯誤訊息。

以下是這個部分的全部程式碼:

from enum import Enum

class BlogType(str, Enum):
business = "business"
story = "story"
qa = "qa"


@app.get("/blog/type/{type}")
def get_blog_type(type: BlogType):
return {"message":f"Blog 的資料型態是 {type}"}

查詢參數Query parameters

它是指在 URL 中使用問號,並且在問號( ? )之後由「和符號」( & )分隔的一系列的鍵值( key=value )對。瀏覽的網址看起來會像下面的樣子:

http://127.0.0.1:8000/blog/all?page=2&page_size=10

查詢參數本身並不是路徑的一部分。以下面的程式碼為例,路徑的部分為/blog/all( http://127.0.0.1:8000/blog/all ),而page 與page_size為查詢參數( page=2&page_size=10 )。因此,可以說是以「和符號」( & )作為分界點。

@app.get("/blog/all")
def get_blogs_all(page, page_size):
return {"message": f"所有的 blogs: 來自第 {page} 頁, 總共有 {page_size} 筆資料"}

你會得到下面的結果:

又例如,在 URL /items?skip=0&limit=10 中,skiplimit 都是查詢參數。你可以在 FastAPI 應用程式的路由函數中使用相同的名稱作為參數來接收這些值。在 FastAPI 中,查詢參數常用於排序、過濾等操作。

#查詢參數可以設定預設參數值

再回到前面的程式碼:

@app.get("/blog/all")
def get_blogs_all(page, page_size):
return {"message": f"所有的 blogs: 來自第 {page} 頁, 總共有 {page_size} 筆資料"}

我們也可以對查詢參數設定預設值,例如我們可以將page的預設值設定為1,page_size的預設值設定為10( page=1, page_size=10):

@app.get("/blog/all")
def get_blogs_all(page =1,page_size=10):
return {"message": f"所有的 blogs: 來自第 {page} 頁, 總共有 {page_size} 筆資料"}

即使只是輸入 http://127.0.0.1:8000/blog/all 的URL,也會得到下面的結果:

因為我們已經將查詢參數的預設值設定為 page=1, page_size=10 了。

# 查詢參數的驗證方式:Optional

查詢參數還可以使用Optional來處理驗證。首先,匯入Optional套件:

from typing import Optional

修改get_blogs_all,將page_size由固定數字改為Optional。並且在Optional後面加上資料型態,在這裡使用int並且讓他等於None。


@app.get("/blog/all")
def get_blogs_all(page=1, page_size: Optional[int] = None):
return {"message": f"所有的 blogs: 來自第 {page} 頁, 總共有 {page_size} 筆資料"}

在這裡需要在FastAPI的 Swagger UI 下進行測試。

請輸入網址 http://127.0.0.1:8000/docs 。你會看到FastAPI強大的測試工具。

接著,點擊/blog/all打開。您會看到下面的畫面:

點選畫面上的Try It Out按鈕,就可以進行測試。

如果在欄位中放入數字(例如10),會得到正確結果。

但是,若在page_size的位置輸入字串(例如:abc),就會出現錯誤。

因此,使用Optional也可以來處理查詢參數的驗證。

FastAPI的應用

經過前面的介紹,相信您已經對FastAPI有了基本的了解。接下來,讓我們來看看FastAPI在實際開發中可以如何發揮它的效用。

首先,FastAPI快速、簡單的特性讓它在開發API方面的表現相當優秀。您可以快速地建立各種RESTful API,並且由於FastAPI具備自動文件產生功能,在API的管理和使用上都變得非常方便。

FastAPI還支援OAuth2認證、跨網域請求等功能,讓你的API更具有安全性和可用性。另外,FastAPI的非同步處理能力使得它在開發即時應用(如聊天室、遊戲等)上具有強大的優勢。你可以使用Python的async/await語法來撰寫API。

最後,由於FastAPI使用了現代Python的type hints,使得你的程式碼具備更多的可讀性和可維護性。這對於團隊合作或是使用期間較長的專案來說,都是非常有價值的。

結語

透過這篇文章,我們揭開了FastAPI框架的神秘面紗。

從基本特性到實際應用,FastAPI展現了驚人的優勢。不論是其簡潔易懂的語法、快速的執行速度、自動化的文件生成,還是對非同步處理的強大支援,都使FastAPI成為當今Python web框架中的熱門選擇之一。 不管您是Python的熱愛者,還是初次踏入程式設計的新手,FastAPI都值得您一探究竟。希望這篇文章能幫助您輕鬆上手FastAPI,並在您的開發旅程中提供些許幫助。

--

--

Sean Yeh
Python Everywhere -from Beginner to Advanced

# Taipei, Internet Digital Advertising,透過寫作讓我們回想過去、理解現在並思考未來。並樂於分享,這才是最大贏家。