Library、SDK、Framework、API 到底差在哪?先看誰呼叫誰
Library(函式庫)提供可由程式主動呼叫的功能;SDK(軟體開發套件)提供針對特定平台或服務的開發工具組合;Framework(框架)通常掌握主要執行流程,並在約定時機呼叫你提供的程式;API(應用程式介面)則是雙方約定如何使用能力的介面。 四者不是互斥的產品分類:一個 SDK 可以包含 library、提供 API 的包裝,而 framework 本身也會提供 API。
你已經能從第三篇〈從一段 Python 走到一個可重跑的小專案〉找到入口與函數。本篇不再重教 import 或拆檔,而是回答遇到陌生工具時更關鍵的問題:入口在誰手上?下一個函數由誰呼叫?資料交給誰?出錯先看哪一層?
目錄
四個名稱描述的不是同一個維度
| 名稱 | 核心角色 | 一般由誰決定何時使用 | 遇到問題先看 |
|---|---|---|---|
| Library(函式庫) | 已寫好的可重用功能,例如 Python 標準函式庫 statistics |
你的程式決定何時呼叫 | 傳入值與函數契約 |
| SDK(軟體開發套件) | 面向某平台的開發工具組合,可能包含 library、範例、文件與其他工具 | 你的程式呼叫其中的介面;不保證所有 SDK 都相同 | SDK 的方法、設定與版本,以及底層服務 |
| Framework(框架) | 提供應用程式骨架與部分生命週期,依規則呼叫使用者程式 | 框架通常決定何時觸發你登記的處理函數 | 登記規則、生命週期、傳入資料 |
| API(應用程式介面) | 定義可用操作及輸入/輸出的契約 | 由該介面的呼叫者發起 | 名稱、參數、回傳與錯誤契約 |
API 不等於網路請求。 statistics.mean([10, 20]) 也是在使用 Python 函式提供的程式介面;服務提供的 API 則可能透過 SDK 使用。至於外部服務的一次 HTTP 請求與 JSON 回應,留到系列第七篇再深入,避免把「介面是什麼」和「資料怎麼跨網路傳」混成一件事。
同一個需求,控制權可以放在不同地方
假設我們要把合成的學習分鐘數算出平均值。
寫法 A:程式主動呼叫 library。
from statistics import mean
minutes = [10, 20, 30]
average = mean(minutes)
print(f"average={average:.1f}")
這裡是你啟動 Python → 你的程式呼叫 mean → library 回傳 20 → 你的程式印出結果。Library 沒有決定你的主程式何時開始、下一步要做什麼。
寫法 B:把處理函數交給控制流程。 真正的 framework 不只是「有 callback(回呼函數:先交給另一段程式,在約定時機由對方呼叫)的 library」:它通常還管理啟動、事件派送、設定或其他生命週期。為了看清楚呼叫方向,下面只實作一個教學用極簡框架模擬器,不宣稱它是正式框架,也不要求安裝任何產品。
你啟動 main()
→ 教學用 Runner.run() 掌控迴圈
→ Runner 呼叫你登記的 on_record(record)
→ on_record 回傳結果
→ Runner 收集結果
差別不是「框架不用寫程式」,而是你把何時呼叫處理函數的決定權交給了 Runner。這個方向經常稱為控制反轉(Inversion of Control,IoC):不是程式隨時主動呼叫框架的所有功能,而是框架在約定的時機反過來呼叫你的程式。實際工具可能同時存在兩種方向,必須看具體執行入口,不能只靠名稱判斷。
SDK 又位在哪裡?以 AWS 官方 Boto3 文件的低階 client 為例:應用程式先建立 client,再由程式呼叫 client 提供的服務操作方法;該 client 對應 AWS 服務 API。呼叫方向是「你的程式 → Boto3 client(SDK 提供的程式介面)→ 服務操作」,回傳值或錯誤再交回呼叫端。這裡僅分析官方文件的介面關係,沒有安裝 Boto3、建立 client、設定帳號或呼叫 AWS 服務。SDK 不是 API 的另一個名字:API 是可用操作的契約,SDK 是協助開發者使用這些能力的一套工具。沒有指定真實產品時,不應虛構所有 SDK 都會自動重試、驗證或處理認證。
重跑練習:看見框架模擬器反過來呼叫函數
在新資料夾 control-flow-lab 建立一個 main.py,使用 Python 3 執行。以下全部是合成資料與示範程式,只用 Python 標準功能、不連線、不安裝套件。
# main.py — educational framework simulator, not a production framework
from statistics import mean
class Runner:
def __init__(self):
self.handler = None
def register(self, handler):
if not callable(handler):
raise TypeError("handler must be callable")
self.handler = handler
def run(self, batches):
if self.handler is None:
raise RuntimeError("no handler registered")
output = []
for batch in batches:
print("Runner -> handler")
output.append(self.handler(batch))
return output
def on_record(values):
if not values:
raise ValueError("empty batch")
return round(mean(values), 1)
def main():
runner = Runner()
runner.register(on_record)
print(runner.run([[10, 20, 30], [40, 50]]))
if __name__ == "__main__":
main()
從資料夾執行:
python main.py
Codex R1 實跑觀察(Windows/PowerShell/Python 3.14.6;不是所有 Python 版本保證):
Runner -> handler
Runner -> handler
[20, 45]
先預測再改:把第二筆輸入改成 [40, 50, 60],你應預期第二個結果變成 50,但 Runner -> handler 仍印兩次。資料內容改變,不一定會改變呼叫次數。
控制錯誤:定位失敗的責任層次
先保留原檔,每次只做一個修改,觀察錯誤後還原。
- 把
runner.register(on_record)暫時註解。預期RuntimeError: no handler registered:Runner 需要的登記條件未成立,錯誤在模擬器使用契約,不是 Python 語法錯。 - 還原登記後,把第二筆改成
[]。預期先印兩次Runner -> handler,再從on_record拋出ValueError: empty batch:Runner 已正確派送,失敗來自你提供的處理函數對輸入的要求。 - 再還原輸入;將
runner.register(on_record)改為runner.register("on_record")。預期TypeError: handler must be callable:名稱字串不是可呼叫的函數物件。這是登記參數錯誤,不必重寫整個 Runner。
上述六個情境(library 範例、正常流程、輸入變體、三個控制錯誤)已由 Codex 在 Windows/PowerShell/Python 3.14.6 實跑;失敗案例預期以非零結束碼結束。這只驗證列出的程式和環境,不代表所有 Python 版本或真實框架均通過。若執行結果不同,先讀 traceback 最後一行的例外型別,再往上找是哪個函數提出例外、誰把資料交給它。不要看到 framework 或 SDK 的字樣就將問題歸咎於 Python 語法或網路。
面對陌生工具,用四個問題判斷
拿到一份教學或程式碼,先標出:
- 誰啟動? 你執行
main.py、呼叫一個 library 函數,還是由 framework 的執行器啟動? - 誰呼叫誰? 你的程式呼叫套件,還是框架透過登記、繼承或事件機制呼叫你的 callback(回呼函數)?
- 資料怎麼走? 入口收到什麼、傳給哪個介面、回傳什麼;哪些細節被 SDK/框架封裝?
- 失敗在哪一層? 是 Python 語法、登記契約、callback 邏輯,還是外部服務?只依可觀察的錯誤與文件判斷,不憑工具名稱猜。
選工具也從需求出發:只缺一個轉換功能,先找適合的 library;需要使用特定平台的多項能力,再評估它提供的 SDK;需要既定生命週期、路由或事件管理,才考慮 framework。不是抽象層越多就越進階。抽象省掉重複控制流程,也隱藏部分執行細節;好處與診斷成本必須一起看。
驗收與停止線
不看程式答案,試著畫出兩段箭頭:「你 → mean → 回傳」與「你啟動 Runner → Runner → on_record → Runner」。能指出三次控制錯誤分別在哪個契約邊界、能修改不同輸入並預測結果,就是本篇的最低驗收;真正能力仍須以你親自執行並解釋輸出為證據。
到這裡就可以進下一篇。 不必為了比較安裝 FastAPI、Django 或多套 SDK,也不要求重構現有專案。先前的 Python 執行環境、資料流與小專案各有自己的教學範圍;Git 留給第五、六篇,HTTP/JSON 的服務呼叫留給第七篇。第七篇尚未提供已驗證的公開 URL,因此不預先建立連結。
教材依據:《AI_Engineering_Foundations_v1.0》課程節 S04(2026-09-23;保留摘錄為第 12 頁擷取文字),以及已接受的 AI Engineering Foundations 系列規劃。本篇的 Runner 是為說明控制權而設計的合成示例,不代表任何真實 framework 的完整行為。
技術資料與證據界線
以下資料於 2026-10-08 查閱;產品文件隨版本可能更新。課程的篇章界線另依《AI_Engineering_Foundations_v1.0》S04(2026-09-23)及已接受的系列規劃。
- Python 官方
statistics文件:mean的用途、輸入與回傳;round(mean(values), 1)不保證結果必然是 float,本文採實跑輸出。 - MDN:API 定義:API 是軟體元件之間的介面,不限於網路服務。
- AWS:SDK 概念與Boto3 官方 client 文件:區分 SDK 工具與服務操作介面;Boto3 僅作文件分析,未執行。
- Martin Fowler:Inversion of Control與Flask 官方生命週期文件:框架在生命週期中管理並呼叫已登記處理邏輯;本篇 Runner 仍只是教學模擬器,並未驗證 Flask。