1. はじめに

Python は、データ サイエンティスト、ウェブ アプリケーション デベロッパー、システム管理者などが使用する一般的なオープンソース プログラミング言語です。
Cloud Functions は、イベント ドリブンのサーバーレス コンピューティング プラットフォームです。Cloud Functions を使用すると、リソースのプロビジョニングや、変化する要件に対応するためのスケーリングを気にすることなく、コードを記述できます。
Cloud Functions の関数には次の 2 つのタイプがあります。
- HTTP 関数は HTTP リクエストに応答します。この Codelab では、いくつかのビューを作成します。
- バックグラウンド関数は、Cloud Pub/Sub へのメッセージのパブリッシュや Cloud Storage へのファイルのアップロードなどのイベントによってトリガーされます。このラボではこれについて説明しませんが、ドキュメントで詳細を確認できます。

この Codelab では、Python で独自の Cloud Functions を作成する方法について説明します。
作成するアプリの概要
この Codelab では、HTTP 経由で呼び出すと 「Python Powered」ロゴを表示する Cloud Functions を公開します。

学習内容
- HTTP Cloud Functions の関数を作成する方法。
- 引数を取る HTTP Cloud Functions の関数を作成する方法。
- HTTP Cloud Functions をテストする方法。
- 関数を試すためにローカルの Python HTTP サーバーを実行する方法。
- 画像を返す HTTP Cloud Functions の関数を作成する方法。
2. 設定と要件
セルフペース型の環境設定
- Google Cloud Console にログインして、プロジェクトを新規作成するか、既存のプロジェクトを再利用します。Gmail アカウントも Google Workspace アカウントもまだお持ちでない場合は、アカウントを作成してください。



- プロジェクト名は、このプロジェクトの参加者に表示される名称です。Google API では使用されない文字列です。いつでも更新できます。
- プロジェクト ID は、すべての Google Cloud プロジェクトにおいて一意でなければならず、不変です(設定後は変更できません)。Cloud コンソールでは一意の文字列が自動生成されます。通常は、この内容を意識する必要はありません。ほとんどの Codelab では、プロジェクト ID(通常は
PROJECT_IDと識別されます)を参照する必要があります。生成された ID が好みではない場合は、ランダムに別の ID を生成できます。または、ご自身で試して、利用可能かどうかを確認することもできます。このステップ以降は変更できず、プロジェクトを通して同じ ID になります。 - なお、3 つ目の値として、一部の API が使用するプロジェクト番号があります。これら 3 つの値について詳しくは、こちらのドキュメントをご覧ください。
- 次に、Cloud のリソースや API を使用するために、Cloud コンソールで課金を有効にする必要があります。この Codelab の操作をすべて行って、費用が生じたとしても、少額です。このチュートリアルの終了後に請求が発生しないようにリソースをシャットダウンするには、作成したリソースを削除するか、プロジェクトを削除します。Google Cloud の新規ユーザーは、300 米ドル分の無料トライアル プログラムをご利用いただけます。
Cloud Shell の起動
Google Cloud はノートパソコンからリモートで操作できますが、この Codelab では、Cloud Shell(Cloud 上で動作するコマンドライン環境)を使用します。
Cloud Shell をアクティブにする
- Cloud Console で、[Cloud Shell をアクティブにする]
をクリックします。

Cloud Shell を初めて起動する場合は、その内容を説明する中間画面が表示されます。中間画面が表示された場合は、[続行] をクリックします。

すぐにプロビジョニングが実行され、Cloud Shell に接続されます。

この仮想マシンには、必要な開発ツールがすべて用意されています。仮想マシンは Google Cloud で稼働し、永続的なホーム ディレクトリが 5 GB 用意されているため、ネットワークのパフォーマンスと認証が大幅に向上しています。このコードラボで行う作業のほとんどはブラウザから実行できます。
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 API と Cloud Build API が有効になっていることを確認する
Cloud Shell から次のコマンドを実行して、Cloud Functions API と Cloud Build API が有効になっていることを確認します。
gcloud services enable \ cloudfunctions.googleapis.com \ cloudbuild.googleapis.com
注: Cloud Build は gcloud functions deploy コマンドによって呼び出され、コードを自動的にコンテナ イメージにビルドします。
ソースコードをダウンロードする
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 関数として記述されます。この関数は、通常 request という名前の 1 つの flask.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 Functions としてデプロイしましょう。
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 をクリックします。次のコマンドを使用して、URL をプログラムで取得し、関数を呼び出すこともできます。
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
次のような結果が表示されます。
Hello World! 👋
4. 引数を取る HTTP Cloud Functions の関数を作成する
関数は、引数を受け取ると汎用性が高まります。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 をクリックします。次のコマンドを使用して、URL をプログラムで取得し、関数を呼び出すこともできます。
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
デフォルトの結果が表示されます。
Hello World! 🚀
name 引数が設定されていないため、デフォルトの結果が返されます。URL にパラメータを追加します。
curl -w "\n" $URL?name=YOUR%20NAME
今回は、カスタムの応答が返されます。
Hello YOUR NAME! 🚀
次のステップでは、ソースコードが更新されたときに関数が意図したとおりに動作し続けるように、単体テストを追加します。
5. テストの作成
Python の HTTP Cloud Functions は、標準ライブラリの unittest モジュールを使用してテストします。関数をテストするためにエミュレータやその他のシミュレーションを実行する必要はなく、通常の 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パラメータをモック(つまり、テストに必要な特定のデータを含む偽のオブジェクトに置き換える)して、関数の 1 つをテストします。 - 各関数を呼び出した後、テストは HTTP レスポンスをチェックして、想定どおりであることを確認します。
main.py は flask に依存するため、テスト環境に Flask フレームワークがインストールされていることを確認します。
pip install flask
Flask をインストールすると、次のような結果が出力されます。
Collecting flask ... Successfully installed ... flask-3.0.2 ...
これらのテストをローカルで実行します。
python -m unittest
3 つの単体テストが合格するはずです。
... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK
次に、「Python Powered」ロゴを返す新しい関数を作成します。
6. 「Python Powered」HTTP Cloud Functions の関数を作成する
リクエストごとに「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 URL をクリックします。すべてが正常に機能している場合、新しいブラウザタブに「Python Powered」ロゴが表示されます。
次に、デプロイ前に関数をローカルで実行して試せるように、アプリを作成します。
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()という名前の関数で処理される基本 URL にルートを登録します。 - 次に、
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 でプレビュー] を選択します。

プロキシ サービスのプレビュー用 URL が新しいブラウザ ウィンドウで開きます。ウェブ プレビューでは、HTTPS でのアクセスはユーザー アカウントのみに制限されます。すべてが正常に機能している場合、「Python Powered」ロゴが表示されます。

8. 完了

Flask フレームワークを使用してウェブ リクエストを処理する慣用的な関数を使用して、HTTP Cloud Functions をデプロイしました。
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 の使用をお楽しみください。