皆さんこんにちは。大学のレポート課題に殺されかけているmk419です。
今回はFast APIについてざっくり紹介していきます。
Fast APIとは?
APIとかWebアプリを構築出来る、Pythonで書かれたWebフレームワークです。
Fast APIの特徴
とても速い
Fast APIはNode JSやGoと真正面から殴り合えます。DjangoやFlaskより、ずっとはやい!!
コード量が少ない
下記の例を見れば分かると思いますが、Flask並の記述量で動かせます。
セットアップ
sudo pacman -S python-fastapi uvicorn
お好みでpython-jinjaとかpython-aiofilesとか入れてください。
注意: 今回のコードはPython 3.9以上の環境で動きます!!!
例1
JSONを返す単純なものです。
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World!"}
main.pyで保存してください。
実行
uvicorn main:app --reload
結果
デフォルトのURLはhttp://127.0.0.1:8000/となっています。
{"message":"Hello World!"}
上記と同じものが帰ってきたら成功です。
解説
@app.getでパスの指定を行っています。
Dict型を返すと自動的にJSONに変換してくれます。
例2
パスパラメータを使用したものです。
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World!"}
@app.get("/name/{name}")
async def hello_name(name: str):
return {"message": f"Hello {name}!"}
実行等は例1と同様なので省略。
結果
http://127.0.0.1:8000/name/mk419にアクセスすると、下記のようになります。
{"message":"Hello mk419!"}
解説
@app.getでパスパラメータnameの値が引数nameに代入されます。
型の変換は自動でやってくれます。
例3
例2にクエリパラメータを付けたものです。
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World!"}
@app.get("/name/{name}")
async def hello_name(name: str, year: int = 18):
return {"message": f"Hello {name}! I am {year} years old."}
結果
http://127.0.0.1:8000/name/mk419?year=10にアクセスすると、下記のようになります。
{"message":"Hello mk419! I am 10 years old."}
例4
POSTを使えるようにしたものです。
from fastapi import FastAPI
from pydantic import BaseModel
class Data(BaseModel):
name: str
year: int = 18
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World!"}
@app.get("/name/{name}")
async def hello_name(name: str, year: int = 18):
return {"message": f"Hello {name}! I am {year} years old."}
@app.post("/name")
async def hello_name_post(data: Data):
return {"message": f"Hello {data.name}! I am {data.year} years old."}
結果
curl -X POST -H "Content-Type: application/json" -d '{"name":"mk419", "year": 10}' http://127.0.0.1:8000/name
例3と同じ結果になります。
解説
Fast APIはリクエストボディをPydanticで定義します。
型のチェックに引っかかるとエラーを吐いてくれます。
例5
チャットアプリ的な何かです。
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponse
from pydantic import BaseModel
HTML = """
<!DOCTYPE html>
<html>
<head>
<title>Fast API</title>
</head>
<body>
<form action="" onsubmit="sendMessage(event)">
<label>Name: <input type="text" id="name" autocomplete="off" /></label>
<hr>
<label>Message: <input type="text" id="message" autocomplete="off" /></label>
<button>Send</button>
</form>
<ul id="messageList">
</ul>
<script>
let websocket = new WebSocket("ws://127.0.0.1:8000/websocket");
websocket.onmessage = function (event) {
let messageList = document.getElementById("messageList")
let item = document.createElement("li")
let content = document.createTextNode(event.data)
item.appendChild(content)
messageList.appendChild(item)
};
function sendMessage(event) {
let name = document.getElementById("name")
let message = document.getElementById("message")
let data = {
"name": name.value,
"message": message.value
};
let json = JSON.stringify(data);
websocket.send(json)
message.value = ""
event.preventDefault()
}
</script>
</body>
</html>
"""
app = FastAPI()
connection_list: list[WebSocket] = []
message_list: list[str] = []
class Data(BaseModel):
name: str = "匿名"
message: str
@app.get("/", response_class=HTMLResponse)
async def root():
return HTMLResponse(HTML)
@app.websocket("/websocket")
async def websocket_connection(websocket: WebSocket):
await websocket.accept()
connection_list.append(websocket)
for message in message_list:
await websocket.send_text(message)
try:
while True:
data = await websocket.receive_json()
name = "匿名" if data['name'] == "" else data['name']
message = f"{name}: {data['message']}"
message_list.append(message)
for connection in connection_list:
await connection.send_text(message)
except WebSocketDisconnect:
connection_list.remove(websocket)
色々ツッコミ所はあると思いますが、許してください()
結果
http://127.0.0.1:8000/にアクセスすると、下記のように動きます。

解説
HTML
<!DOCTYPE html>
<html>
<head>
<title>Fast API</title>
</head>
<body>
<form action="" onsubmit="sendMessage(event)">
<label>Name: <input type="text" id="name" autocomplete="off" /></label>
<hr>
<label>Message: <input type="text" id="message" autocomplete="off" /></label>
<button>Send</button>
</form>
<ul id="messageList">
</ul>
<script>
let websocket = new WebSocket("ws://127.0.0.1:8000/websocket");
websocket.onmessage = function (event) {
let messageList = document.getElementById("messageList")
let item = document.createElement("li")
let content = document.createTextNode(event.data)
item.appendChild(content)
messageList.appendChild(item)
};
function sendMessage(event) {
let name = document.getElementById("name")
let message = document.getElementById("message")
let data = {
"name": name.value,
"message": message.value
};
let json = JSON.stringify(data);
websocket.send(json)
message.value = ""
event.preventDefault()
}
</script>
</body>
</html>
WebSocketを使用してサーバー側と通信しています。
Python
HTMLResponseでHTMLを返すことが出来ます。@app.getのresponse_classで返すレスポンスの型を指定します。
for message in message_list:
await websocket.send_text(message)
初回アクセス時に過去のメッセージをクライアントに送信します。
for connection in connection_list:
await connection.send_text(message)
送ったメッセージを現在接続中の全てのクライアントに送信します。
まとめ
今回はFast APIをちょっとだけ紹介しました。
今回は紹介しませんでしたが、SQLとの連携とかGraphQLの実装とか色々な用途で使えます。
自分はサーバーよわよわ人間なので、これぐらいの例しか挙げられませんでした()
Fast APIは良いぞ!!!
コメント