1. 簡介
Python 是熱門的開放原始碼程式設計語言,可供數據資料學家、網頁應用程式開發人員、系統管理員等人使用。
Cloud Functions 是事件導向的無伺服器運算平台。Cloud Functions 可讓您編寫程式碼,無須擔心佈建資源或調度資源來因應不斷變化的需求。
Cloud Functions 有兩種類型:
- HTTP 函式會回應 HTTP 要求。您將在本程式碼研究室中建構幾個項目。
- 背景函式是由事件觸發,例如發布至 Cloud Pub/Sub 的訊息或上傳至 Cloud Storage 的檔案。本研究室在這個研究室中不會探討這個問題,但您可以參閱說明文件來瞭解詳情。
本程式碼研究室將逐步引導您使用 Python 建立自己的 Cloud Functions。
建構項目
在本程式碼研究室中,您將發布透過 HTTP 叫用的 Cloud 函式,該函式會顯示「Python Powered」標誌:
課程內容
- 如何編寫 HTTP Cloud 函式。
- 如何編寫使用引數的 HTTP Cloud 函式。
- 如何測試 HTTP Cloud 函式。
- 如何執行本機 Python HTTP 伺服器以嘗試此函式。
- 如何編寫會傳回圖片的 HTTP Cloud 函式。
2. 設定和需求
自修環境設定
- 登入 Google Cloud 控制台,建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶。
- 「專案名稱」是這項專案參與者的顯示名稱。這是 Google API 未使用的字元字串。您可以隨時更新付款方式。
- 所有 Google Cloud 專案的專案 ID 均不得重複,而且設定後即無法變更。Cloud 控制台會自動產生一個不重複的字串。但通常是在乎它何在在大部分的程式碼研究室中,您必須參照專案 ID (通常為
PROJECT_ID
)。如果您對產生的 ID 不滿意,可以隨機產生一個 ID。或者,您也可以自行嘗試,看看是否支援。在這個步驟後,這個名稱即無法變更,而且在專案期間內仍會保持有效。 - 資訊中的第三個值是專案編號,部分 API 會使用這個編號。如要進一步瞭解這三個值,請參閱說明文件。
- 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Cloud 資源/API。執行本程式碼研究室不會產生任何費用 (如果有的話)。如要關閉資源,以免產生本教學課程結束後產生的費用,您可以刪除自己建立的資源或刪除專案。新使用者符合 $300 美元免費試用計畫的資格。
啟動 Cloud Shell
雖然 Google Cloud 可以從筆記型電腦遠端操作,但在本程式碼研究室中,您將使用 Cloud Shell,這是一種在 Cloud 中執行的指令列環境。
啟用 Cloud Shell
- 在 Cloud 控制台中,按一下「啟用 Cloud Shell」圖示 。
如果您是第一次啟動 Cloud Shell,系統會顯示中繼畫面,說明這項服務的內容。如果系統顯示中繼畫面,請按一下「繼續」。
佈建並連線至 Cloud Shell 只需幾分鐘的時間。
這個虛擬機器已載入所有必要的開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,大幅提高網路效能和驗證能力。在本程式碼研究室中,您的大部分作業都可透過瀏覽器完成。
連線至 Cloud Shell 後,您應會發現自己通過驗證,且專案已設為您的專案 ID。
- 在 Cloud Shell 中執行下列指令,確認您已通過驗證:
gcloud auth list
指令輸出
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- 在 Cloud Shell 中執行下列指令,確認 gcloud 指令知道您的專案:
gcloud config list project
指令輸出
[core] project = <PROJECT_ID>
如果尚未設定,請使用下列指令進行設定:
gcloud config set project <PROJECT_ID>
指令輸出
Updated property [core/project].
確保已啟用 Cloud Functions 和 Cloud Build API
透過 Cloud Shell 執行下列指令,確認 Cloud Functions 和 Cloud Build API 已啟用:
gcloud services enable \ cloudfunctions.googleapis.com \ cloudbuild.googleapis.com
注意:gcloud functions deploy
指令會呼叫 Cloud Build,並自動將程式碼建構成容器映像檔。
下載原始碼
在 Cloud Shell 終端機執行下列指令:
REPO_NAME="codelabs" REPO_URL="https://github.com/GoogleCloudPlatform/$REPO_NAME" SOURCE_DIR="cloud-functions-python-http" git clone --no-checkout --filter=blob:none --depth=1 $REPO_URL cd $REPO_NAME git sparse-checkout set $SOURCE_DIR git checkout cd $SOURCE_DIR
查看來源目錄的內容:
ls
您應該會有下列檔案:
main.py python-powered.png test_main.py web_app.py
3. HTTP Cloud Functions 簡介
Python 中的 HTTP Cloud Functions 是以一般 Python 函式編寫。這個函式必須接受單一 flask.Request
引數,該引數通常命名為 request
。
main.py
import flask
def hello_world(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- "Hello World! 👋"
"""
response = "Hello World! 👋"
return flask.Response(response, mimetype="text/plain")
# ...
您可以使用偏好的指令列編輯器 (nano、vim 或 emacs) 開啟檔案。將來源目錄設為工作區後,您也可以在 Cloud Shell 編輯器中開啟這個存放區:
cloudshell open-workspace .
現在,讓我們使用 gcloud functions deploy
指令,將這個函式部署為 HTTP Cloud 函式:
FUNCTION_NAME="hello_world" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
指令輸出:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
gcloud functions deploy
選項相關注意事項:
--runtime
:指定語言執行階段。如果是 Python,目前可為python37
、python38
、python39
、python310
或python312
。請參閱「執行階段」。--trigger-http
:為函式指派端點。傳送至端點的 HTTP 要求 (POST、PUT、GET、DELETE 和 OPTIONS) 會觸發函式執行作業。--allow-unauthenticated
:此函式將公開,允許所有呼叫端,而不用檢查驗證。- 詳情請參閱 gcloud functions deploy。
如要測試函式,請按一下上方指令輸出內容中顯示的 httpsTrigger.url
網址。您也可以透過程式輔助方式擷取網址,並使用下列指令呼叫函式:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
畫面上應會顯示以下結果:
Hello World! 👋
4. 撰寫使用引數的 HTTP Cloud 函式
函式接受引數時,功能會更實用。讓我們定義支援 name
參數的新函式 hello_name
:
main.py
# ...
def hello_name(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- "Hello {NAME}! 🚀" if "name=NAME" is defined in the GET request
- "Hello World! 🚀" otherwise
"""
name = request.args.get("name", "World")
response = f"Hello {name}! 🚀"
return flask.Response(response, mimetype="text/plain")
# ...
讓我們部署這個新函式:
FUNCTION_NAME="hello_name" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
指令輸出:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
如要測試函式,請按一下上方指令輸出內容中顯示的 httpsTrigger.url
網址。您也可以透過程式輔助方式擷取網址,並使用下列指令呼叫函式:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
您應該會看到預設結果:
Hello World! 🚀
你尚未設定 name
引數,因此會收到預設結果。在網址中加入參數:
curl -w "\n" $URL?name=YOUR%20NAME
這次,您會收到自訂回覆:
Hello YOUR NAME! 🚀
下一步是新增單元測試,確保在原始碼更新時,函式仍可正常運作。
5. 撰寫測試
系統會使用標準程式庫的 unittest
模組測試 Python 中的 HTTP Cloud Functions。您不需要執行模擬器或其他模擬即可測試函式,只需使用一般的 Python 程式碼即可。
hello_world
和 hello_name
函式的測試如下所示:
test_main.py
import unittest
import unittest.mock
import main
class TestHello(unittest.TestCase):
def test_hello_world(self):
request = unittest.mock.Mock()
response = main.hello_world(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == "Hello World! 👋"
def test_hello_name_no_name(self):
request = unittest.mock.Mock(args={})
response = main.hello_name(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == "Hello World! 🚀"
def test_hello_name_with_name(self):
name = "FirstName LastName"
request = unittest.mock.Mock(args={"name": name})
response = main.hello_name(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == f"Hello {name}! 🚀"
- Python 測試的編寫方式與其他 Python 檔案相同。從開始一組匯入作業開始,然後定義類別和函式。
- 測試宣告的格式為
class TestHello(TestCase)
。該類別必須是繼承自unittest.TestCase
的類別。 - 測試類別含有方法,每個方法都必須以
test_
開頭,代表個別測試案例。 - 每個測試案例都會模擬
request
參數來測試我們其中一個函式 (也就是以假物件取代為測試所需的特定資料)。 - 叫用每個函式後,測試會檢查 HTTP 回應,確保回應符合預期。
由於 main.py
依附 flask
,因此請確認已在測試環境中安裝 Flask 架構:
pip install flask
安裝 Flask 會輸出類似以下的結果:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
在本機執行以下測試:
python -m unittest
這三個單元測試應通過:
... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK
接下來,您將建立一個新函式,用來傳回「Python Powered」標誌。
6. 寫入「Python 技術提供」HTTP Cloud 函式
讓我們傳回「Python Powered」來建立新函式,讓新函式變得更加有趣吧為每個要求建立映像檔:
下面列出執行程式碼的程式碼:
main.py
# ...
def python_powered(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- The official "Python Powered" logo
"""
return flask.send_file("python-powered.png")
部署新的 python_powered
函式:
FUNCTION_NAME="python_powered" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
指令輸出:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
如要測試函式,請按一下上方指令輸出內容中顯示的 httpsTrigger.url
網址。如果一切運作正常,您會看到「Python power」標誌。
接下來,您將建立應用程式,以便在部署前在本機執行並試用函式。
7. 在本機執行函式
如要在本機執行 HTTP 函式,您可以建立網頁應用程式,並依據路徑呼叫函式。您可以在與函式相同的目錄中新增該目錄。名為 web_app.py
的檔案含有下列內容:
web_app.py
import flask
import main
app = flask.Flask(__name__)
@app.get("/")
def index():
return main.python_powered(flask.request)
if __name__ == "__main__":
# Local development only
# Run "python web_app.py" and open http://localhost:8080
app.run(host="localhost", port=8080, debug=True)
- 這個檔案會建立 Flask 應用程式。
- 它會在基準網址上註冊路徑,並利用名為
index()
的函式處理。 - 接著,
index()
函式會呼叫python_powered
函式,並傳遞目前的要求。
確認您的開發環境已安裝 Flask 架構:
pip install flask
安裝 Flask 會輸出類似以下的結果:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
如要在本機執行這個應用程式,請執行下列指令:
python web_app.py
現在,使用 Cloud Shell 網頁預覽功能,在瀏覽器中測試網頁應用程式。在 Cloud Shell 中,按一下「網頁預覽」按鈕,然後選取「透過以下通訊埠預覽:8080」:
Cloud Shell 會在新的瀏覽器視窗中,開啟相關 Proxy 服務的預覽網址。網頁預覽功能會限制只有您的使用者帳戶可透過 HTTPS 存取。如果一切運作正常,您應該會看到「Python Powered」標誌!
8. 恭喜!
您已部署 HTTP Cloud Functions,使用慣用的函式透過 Flask 架構處理網路要求。
Cloud Functions 定價是按照函式的叫用頻率計算,包括不常執行函式的免費方案。測試完 Cloud Functions 後,您可以使用 gcloud
刪除函式:
gcloud functions delete hello_world --quiet gcloud functions delete hello_name --quiet gcloud functions delete python_powered --quiet
您也可以透過 Google Cloud 控制台刪除函式。
希望您會喜歡在 Python 中使用 Cloud Functions!