National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 02

第一個 Flask 程式

虛擬環境、安裝、路由與 view 函數,在自己的電腦上跑起來
Interaction實作導覽 25 minute(s)

Learning Objectives

  • 說明 Flask 是什麼,以及 WSGI、Werkzeug、Jinja2 各自的角色
  • 用 venv 建立虛擬環境、安裝 Flask,並在自己的電腦上啟動網站
  • 說明 Flask(__name__)、路由與 view 函數的關係
  • 說明除錯模式的 reloader 與 debugger,以及為什麼不能用在正式環境

Flask 是什麼

上一課操作的網站就是用 Flask 寫的。Flask 是 Python 的網頁框架,負責處理 HTTP 的細節,讓你只要寫「這個網址要回什麼」。

它被稱為微框架(microframework):核心很小,資料庫、表單驗證這些都不內建,需要時再選用擴充套件或自己寫。這一軌會直接用 Python 內建的 sqlite3 接資料庫,也比較看得清楚每一步在做什麼。

幾個會反覆看到的名字:

名稱 是什麼
WSGI Python 網頁應用程式與伺服器之間的標準介面。Flask 程式就是一個 WSGI 應用程式
Werkzeug 實作 WSGI 的工具組:解析請求、比對路由、開發用伺服器
Jinja2 模板語言,用來產生 HTML(第 6 課)
MarkupSafe 跳脫 HTML 特殊字元,防止注入
ItsDangerous 替資料簽章,用來保護 Session Cookie(第 14 課)

安裝 Flask 時,這些套件會一起裝好。

在自己的電腦上跑起來

下面的輸出是在 Windows 11、Python 3.12 上實際執行的結果。版本號依你安裝的時間而定,看到較新的版本是正常的。如果手邊沒有電腦可以操作,先往下看,課程裡的範例都能直接在瀏覽器執行。

  1. 1

    建立專案資料夾與虛擬環境

    虛擬環境(virtual environment)是每個專案自己的一組套件,不會和其他專案打架,這是 Python 內建的 venv 模組提供的功能。

    下面是 Windows。macOS 與 Linux 的最後一行改成 python3 -m venv .venv。PowerShell 的 mkdir 會多印一段新資料夾的資訊,這裡省略。

  2. 2

    啟用虛擬環境

    每次開新的終端機都要啟用一次。啟用後,命令列前面會出現 (.venv)。

    系統與終端機 指令
    Windows PowerShell .venv\Scripts\Activate.ps1
    Windows 命令提示字元 .venv\Scripts\activate.bat
    macOS、Linux source .venv/bin/activate

    PowerShell 如果說不允許執行指令碼,先執行 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser(Python 官方文件的建議)。要離開虛擬環境時輸入 deactivate。

  3. 3

    安裝 Flask

    pip install 的下載過程省略,只留最後一行。pip freeze 列出目前環境裝了哪些套件和版本,第 19 課部署時會用它產生 requirements.txt。

  4. 4

    寫 app.py

    在 myproject 資料夾新增 app.py。不要取名叫 flask.py,會和 Flask 本身衝突。

    from flask import Flask
    
    app = Flask(__name__)
    
    
    @app.route('/')
    def index():
        return 'Hello, Flask!'
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    
  5. 5

    啟動開發伺服器

    --app app 指定程式在 app.py,--debug 打開除錯模式。伺服器會一直等待請求,所以命令列不會回來。

    用瀏覽器開 http://127.0.0.1:5000/ 就看到 Hello, Flask!,每個請求都會印一行紀錄(下面最後兩行是開了 / 和不存在的 /nothing)。PIN 碼每台電腦不同。按 Ctrl+C 停止伺服器。127.0.0.1 是你自己的電腦,別人連不到。

    如果出現 OSError,代表 5000 埠已經有別的程式在用,可以改用 flask --app app run --debug --port 5001。macOS 的「AirPlay 接收器」常佔用 5000。

  6. 6

    另一種啟動方式:python app.py

    python app.py 會執行檔案最下面的 app.run(debug=True),輸出幾乎相同。官方文件建議用 flask run,因為 app.run() 的伺服器在重新載入時,遇到錯誤會直接結束。

    app.run() 一定要放在 if __name__ == '__main__': 裡面,否則日後用正式伺服器匯入這個檔案時會干擾。

這段導覽完成了

逐步看:網址怎麼走到函數

瀏覽器的環境不能開真的伺服器,所以課程裡的範例用 client = app.test_client() 當作瀏覽器:client.get('/') 等於瀏覽器請求 /,回傳值就是回應。Flask 本身是真的,只是請求不經過網路。

注意呼叫堆疊:client.get 之後會直接跳進 index,中間 Flask 做的事不顯示。

路由、view 函數與 __name__

  • 路由(route):網址與處理函數的對應關係。
  • view 函數:處理某個網址的函數,它的回傳值會變成回應。
  • 端點(endpoint):路由的內部名稱,預設就是函數名稱,第 3 課的 url_for 會用到。

@app.route('/') 只是登記的簡寫。Flask 另外提供 app.add_url_rule(網址, 端點, 函數),做的事情完全一樣,平常用裝飾器就好,看到別人這樣寫時要認得。

__name__ 是 Python 自動設定的變數:直接執行檔案時是 '__main__',被別的程式匯入時是模組名稱。

逐步看:路由表裡有什麼

app.url_map 就是 Flask 的路由表。看看兩種登記方式的結果,以及表裡多出來的一筆。

除錯模式

--debug 或 debug=True 會打開兩個功能:

功能 做什麼
reloader 監看原始碼,檔案一改就自動重新啟動伺服器
debugger 發生未處理的錯誤時,瀏覽器顯示互動式的錯誤頁面,可以看堆疊,甚至執行 Python

開發時很方便,但是 除錯模式與開發伺服器都不可以用在正式環境。debugger 允許從瀏覽器執行任意 Python 程式,雖然有 PIN 碼保護,仍然是很大的安全風險;開發伺服器也沒有為效率、穩定與安全設計。正式環境怎麼做是第 19 課的內容。

開啟除錯模式時,程式發生錯誤會顯示 debugger;關閉時,使用者只看到簡單的 500 Internal Server Error,詳細的錯誤寫在伺服器紀錄。下面的練習是後者。

互動練習:改程式、加頁面、看錯誤

這個小工具裡的 Flask 也是真的。按「存檔並重新啟動」相當於 reloader 幫你做的事。存檔後畫面會自動重新載入,但自動載入不算任務,要自己按 ↻ 或點連結。

動手做:讀書會網站的兩個頁面

用兩種方式各登記一個路由:/ 用裝飾器,/schedule 用 add_url_rule。程式最下面的測試不要改。

你的輸出
預期輸出

想一想

1.

Flask 為什麼被稱為微框架?

2.

下面的程式會印出什麼?

from flask import Flask
app = Flask(__name__)

@app.route('/hi')
def hi():
    return 'hi'

client = app.test_client()
print(client.get('/hi').status_code, client.get('/').status_code)
3.

為什麼不可以在正式環境開除錯模式?

4.

虛擬環境解決什麼問題?

5.

關於 @app.route('/'),下面哪個說法正確?

第 1 次作答

重點整理

  • 每個專案一個虛擬環境:python -m venv .venv、啟用、pip install flask
  • 啟動:flask --app app run --debug;app.run() 要放在 if __name__ == '__main__': 裡
  • 路由把網址對應到 view 函數,view 函數的回傳值變成回應
  • Flask(__name__) 讓 Flask 找得到模板與靜態檔案
  • 除錯模式的 reloader 和 debugger 只能在開發時使用
  • 課程範例用 app.test_client() 當瀏覽器;在自己的電腦上可以用真的瀏覽器

下一課讓網址可以帶變數,例如 /note/3,並處理不同的 HTTP 方法。

這一課完成了!
Next lesson:路由與動態網址
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。