Python: 建立 REST API

使用 Python 的 Flask 構建 REST API 的逐步指南

👋 歡迎瀏覽 Stackhero 文件!

Stackhero 為您提供即用型的 Python cloud 解決方案,專為簡化您的部署流程而設:

  • 只需一個簡單的 git push,即可於數秒內將您的應用程式部署到生產環境。
  • 支援自訂網域名稱,並為您自動配置 HTTPS 憑證,確保連線安全。
  • 享有自動備份一鍵更新可預測收費,讓您專注於開發程式碼,而無需煩惱基礎設施管理。
  • 專屬私有基礎設施上運行,確保高效能高安全性,您的環境將被隔離及保護。

節省時間簡化您的工作流程:利用 Stackhero 的 Python cloud hosting,您的程式碼最快只需 5 分鐘即可投入運作。

本指南將帶您一步步使用 Python 和 Flask 建立一個簡單的 REST API。Flask 是一個輕量級的 micro-framework,讓您可以快速構建 Web 應用程式及 API。

在開始之前,請確保您已安裝以下工具:

  1. Python
  2. pip
  3. git
  4. asdf

如果您需要協助設定開發環境,請參閱 Development platform 指南。或者,您亦可直接在 Code-Hero 線上平台即時開始編寫程式。Code-Hero 提供線上 IDE 及終端機,所有必要工具均已預先安裝,讓您專注於程式開發,無需煩惱安裝與設定。

Python REST API 在 Code-Hero 執行,可直接於瀏覽器存取Python REST API 在 Code-Hero 執行,可直接於瀏覽器存取

首先建立一個新的專案目錄。本例中,專案名稱為 myRestApi

mkdir myRestApi
cd myRestApi

使用 asdf 設定 Python 為最新版本,並初始化 Git 儲存庫:

asdf install python latest \
  && asdf local python latest

echo "__pycache__/" >> .gitignore

git init
git add -A .
git commit -m "First commit"

本範例只需一個主要依賴:Flask。

Flask 設計簡單且高效,讓您可以無負擔地建立及部署 Web API。它內建路由、模板及 HTTP 請求處理功能,協助您從想法到可運作的 API 只需數分鐘。

您可以使用 pip 安裝 Flask 及 python-dotenv

pip install Flask python-dotenv

我們同時安裝 python-dotenv,以便安全且方便地管理環境變數。稍後步驟會示範其用法。

安裝完成後,請將依賴套件凍結到 requirements.txt

pip freeze > requirements.txt

凍結依賴可確保所有人使用相同版本的套件,這個小動作能為您日後省下大量除錯時間。

現在您可以開始撰寫 API 程式碼。

建立一個名為 app.py 的檔案,並加入以下程式碼:

import os
from dotenv import load_dotenv
from flask import Flask, jsonify, request

# 非 production 環境時,從 .env 載入環境變數
if os.environ.get('ENV') != 'production':
    load_dotenv()

app = Flask(__name__)

# 範例任務資料
tasks = [
    {
        'id': 1,
        'title': 'Buy groceries',
        'description': 'Milk, Cheese, Pizza, Fruits',
        'done': False
    },
    {
        'id': 2,
        'title': 'Learn Python',
        'description': 'Learn Python programming basics',
        'done': False
    }
]

@app.route('/api/tasks', methods=['GET'])
def get_tasks():
    return jsonify({'tasks': tasks})

@app.route('/api/tasks/<int:task_id>', methods=['GET'])
def get_task(task_id):
    task = [task for task in tasks if task['id'] == task_id]
    if not task:
        return jsonify({'error': 'Task not found'}), 404
    return jsonify({'task': task[0]})

@app.route('/api/tasks', methods=['POST'])
def create_task():
    if not request.json or 'title' not in request.json:
        return jsonify({'error': 'Title is required'}), 400
    task = {
        'id': tasks[-1]['id'] + 1,
        'title': request.json['title'],
        'description': request.json.get('description', ""),
        'done': False
    }
    tasks.append(task)
    return jsonify({'task': task}), 201

if __name__ == '__main__':
    if os.environ.get('ENV') == 'production':
        app.run()
    else:
        app.run(host='0.0.0.0', port=8080, debug=True)

您可以使用以下指令啟動伺服器:

python app.py

使用 host='0.0.0.0' 時,您的 API 可於 Code-Hero 透過瀏覽器存取。請前往 http://<XXXXXX>.stackhero-network.com:8080/api/tasks,將 <XXXXXX> 替換為您的 Code-Hero 網域。

伺服器啟動後,您可以使用 cURL 與 API 互動。以下是一些範例指令:

  • 取得所有任務:

    curl -s http://localhost:8080/api/tasks
    # Output:
    # {
    #   "tasks": [
    #     ...
    #   ]
    # }
    
  • 取得指定任務(ID 2):

    curl -s http://localhost:8080/api/tasks/2
    # Output:
    # {
    #   "task": {
    #     ...
    #   }
    # }
    
  • 建立新任務:

    curl -s -X POST -H "Content-Type: application/json" \
    -d '{"title": "New task", "description": "Created with cURL"}' \
    http://localhost:8080/api/tasks
    # Output:
    # {
    #   "task": {
    #     ...
    #   }
    # }
    

小提示:如需更易讀的輸出,可將結果 pipe 給 jq。例如,curl -s http://localhost:8080/api/tasks/2 | jq 會讓 JSON 更易閱讀。

Python REST API 使用 Flask 範例,於 Stackhero Code-Hero 執行,圖中 (1) 為伺服器,(2) 為使用 cURL 的客戶端Python REST API 使用 Flask 範例,於 Stackhero Code-Hero 執行,圖中 (1) 為伺服器,(2) 為使用 cURL 的客戶端

環境變數有助於保護如資料庫密碼或 API 金鑰等敏感資訊。使用環境變數可避免將敏感資料寫入程式碼或 Git 歷史,並方便針對不同環境設定不同參數。

您可以使用 python-dotenv 模組管理環境變數。如果之前未安裝,現在可以補裝:

pip install python-dotenv
pip freeze > requirements.txt

在專案根目錄建立 .env 檔案,加入開發用的環境變數:

ENV="development"
DATABASE_PASSWORD="secretPassword"
THIRD_API_PRIVATE_KEY="secretKey"

.env 加入 .gitignore,避免被提交到 Git:

echo ".env" >> .gitignore

您可以在 Python 內透過 os.environ.get() 讀取這些變數:

import os

print(os.environ.get('ENV'))

.env 檔僅供開發使用。於生產或預備環境,建議直接在 Stackhero 控制台的 Python 服務設定中設置環境變數。

Flask 內建伺服器適合開發用途。生產環境建議使用更穩定的 WSGI 伺服器,例如 Gunicorn。準備方式如下:

  1. 安裝 Gunicorn:

    pip install gunicorn
    pip freeze > requirements.txt
    
  2. 使用 Gunicorn 啟動應用程式:

    ENV=production gunicorn app:app \
      --error-logfile - \
      -b 0.0.0.0:8080
    

    這裡的 app:app 指的是您的檔案(app.py)及 Flask 應用實例(app)。

  3. 您可以新增 Makefile,方便切換開發與生產模式:

    .DEFAULT_GOAL := dev
    
    # Stackhero for Python 預設執行 "run" 規則。我們覆寫為執行 'prod'。
    run: prod
    
    prod:
    	ENV=production gunicorn app:app \
    	  --error-logfile - \
    	  -b 0.0.0.0:8080
    
    dev:
    	python app.py
    

您可以用 make dev(或直接 make)啟動開發模式,或用 make prod 啟動生產模式。

Stackhero 讓雲端部署變得簡單又安全。您可以透過 Python cloud hosting service 部署 Python 專案。主要功能包括:

  • 只需一個 git push 即可部署
  • 自動 TLS (HTTPS) 並支援自訂網域
  • 專屬基礎設施,保障安全
  • 支援 HTTP/2、TLS 1.3、WebSockets、GZIP & Brotli、ETag,以及 TCP/UDP 埠存取

部署步驟如下:

  1. 取得您的 SSH 公鑰:

    cat ~/.ssh/id_*.pub
    
  2. 在 Stackhero 控制台開啟您的「Stackhero for Python」服務,選擇「Configure」。

  3. 將公鑰貼到「SSH public keys」或「Key」欄位。

  4. 點擊「Validate」確認設定。

「Stackhero for Python」公鑰設定畫面「Stackhero for Python」公鑰設定畫面

如果您尚未有 SSH 金鑰,可用以下指令產生:

ssh-keygen -t ed25519

依照 Stackhero 服務提供的指令,將 Git remote 加入專案(請將 <XXXXXX> 替換為您的服務網域):

git remote add stackhero ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git

Git remote 指令畫面Git remote 指令畫面

準備好後,使用以下指令推送程式碼:

git push stackhero main

請記得在部署前先 commit 您的變更。在 Stackhero Code-Hero 中,您可以使用 Command Palette(Ctrl+Shift+PCmd+Shift+P),輸入 Git: Commit 以快速提交。

部署完成後,您的 API 會於 https://<XXXXXX>.stackhero-network.com/api/tasks 上線。請將 <XXXXXX> 替換為您的服務網域,即可存取 Flask API。

您現在已經擁有一個以 Flask 建立的 REST API。以此為基礎,您可以輕鬆擴展應用、連接資料庫,或整合其他服務。Flask 提供靈活性,讓您從簡單原型發展至完整的生產級 API。