1. 總覽
本系列 Codelab (自學式實作教學課程) 旨在協助開發人員瞭解部署應用程式時可用的各種選項。在本程式碼研究室中,您將瞭解如何使用 Python 搭配 Google Cloud Translation API,並在本機執行或部署至 Cloud 無伺服器運算平台 (App Engine、Cloud Functions 或 Cloud Run)。本教學課程的存放區中的範例應用程式可透過 (至少) 八種不同的方式部署,只需進行輕微的設定變更即可:
- 本機 Flask 伺服器 (Python 2)
- 本機 Flask 伺服器 (Python 3)
- App Engine (Python 2)
- App Engine (Python 3)
- Cloud Functions (Python 3)
- Cloud Run (透過 Docker 執行 Python 2)
- Cloud Run (透過 Docker 執行 Python 3)
- Cloud Run (透過 Cloud Buildpacks 執行 Python 3)
本程式碼研究室著重於將此應用程式部署至上述粗體字的平台。
您將學到如何
- 使用 Google Cloud API,特別是 Cloud Translation API (進階/v3)
- 在本機執行基本網頁應用程式,或部署至 Cloud 無伺服器運算平台
軟硬體需求
- Google Cloud 專案 (含有效的 Cloud Billing 帳戶)
- 已安裝 Flask 以便在本機執行,或已啟用 Cloud 無伺服器運算平台以便進行雲端部署
- 基本 Python 技能
- 具備基本作業系統指令的操作知識
問卷調查
您要如何使用這個教學課程?
請評估您使用 Python 的體驗。
請評估你使用 Google Cloud 服務的體驗。
2. 設定和需求
自助式環境設定
- 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請務必建立帳戶。
- 「Project name」是這個專案參與者的顯示名稱。這是 Google API 不會使用的字元字串,您隨時可以更新。
- 專案 ID 在所有 Google Cloud 專案中不得重複,且無法變更 (設定後即無法變更)。Cloud 控制台會自動產生專屬字串,您通常不需要特別留意。在大多數程式碼研究室中,您需要參照專案 ID (通常會以
PROJECT_ID
表示),因此如果不喜歡這個 ID,可以產生另一個隨機 ID,也可以嘗試使用自己的 ID,看看是否可用。然後在專案建立後「凍結」。 - 第三個值是專案編號,部分 API 會使用這個值。如要進一步瞭解這三個值,請參閱說明文件。
- 接著,您需要在 Cloud 控制台中啟用帳單功能,才能使用 Cloud 資源/API。執行本程式碼研究室時,費用應該不會太高,甚至可能不收費。如要關閉資源,避免產生教學課程以外的帳單費用,請按照程式碼研究室結尾的「清除」操作說明進行。Google Cloud 新使用者可享有 $300 美元的免費試用期。
3. 啟用 Translation API
針對範例應用程式,您將使用下方提供的類似操作說明,改為啟用 Cloud Translation API 和 App Engine 服務。
啟用 Cloud API
簡介
無論您要在應用程式中使用哪個 Google API,都必須啟用該 API。以下範例說明啟用 Cloud Vision API 的兩種方式。瞭解如何啟用一個 Cloud API 後,您就能啟用其他 API,因為兩者的程序相似。
選項 1:透過 Cloud Shell 或指令列介面
雖然大多數開發人員會透過 Cloud 控制台啟用 API,但有些開發人員則偏好透過指令列執行所有操作。如要這樣做,您必須查詢 API 的「服務名稱」。這個字串看起來像是網址:SERVICE_NAME
.googleapis.com
。您可以在支援的產品圖表中找到這些產品,也可以使用 Google Discovery API 以程式輔助方式查詢這些產品。
有了這些資訊,您就可以使用 Cloud Shell (或已安裝 gcloud
指令列工具的本機開發環境) 啟用 API,步驟如下:
gcloud services enable SERVICE_NAME.googleapis.com
舉例來說,下列指令可啟用 Cloud Vision API:
gcloud services enable vision.googleapis.com
這個指令會啟用 App Engine:
gcloud services enable appengine.googleapis.com
您也可以透過單一要求啟用多個 API。舉例來說,下列指令列會啟用 Cloud Run、Cloud Artifact Registry 和 Cloud Translation API:
gcloud services enable artifactregistry.googleapis.com run.googleapis.com translate.googleapis.com
選項 2:透過 Cloud Console
您也可以在 API Manager 中啟用 Vision API。在 Cloud Console 中,前往 API Manager,然後選取「Library」。
如果您想啟用 Cloud Vision API,請在搜尋列中開始輸入「vision」,系統就會顯示與您目前輸入內容相符的項目:
選取要啟用的 API,然後按一下「啟用」:
費用
雖然許多 Google API 可免費使用,但 Google Cloud 產品和 API 不是免費。啟用 Cloud API 時,系統可能會要求您提供有效的帳單帳戶。不過,請務必注意,部分 Google Cloud 產品提供「永久免費」等級 (每日/每月),您必須超過這個等級,系統才會向您收取帳單費用;否則,系統不會向您的信用卡 (或指定的帳單付款工具) 收費。
使用者應在啟用任何 API 前參考定價資訊,特別是注意是否有免費方案,如果有的話,請查看相關資訊。如果您要啟用 Cloud Vision API,請查看定價資訊頁面。Cloud Vision 提供免費配額,只要總用量 (每月) 不超過配額,就不會產生任何費用。
每個 Google API 的定價和免費方案皆不相同。範例:
- Google Cloud/GCP:每項產品的計費方式不同,通常是按 vCPU 週期、儲存空間使用者、記憶體用量或按次計費;請參閱上述免費方案資訊。
- Google 地圖:提供一套 API,並為使用者提供總計 $200 美元的免費月額度。
- Google Workspace (前身為 G Suite) API:提供免費使用量 (上限為特定數量),由 Workspace 月費訂閱費用支付,因此使用 Gmail、Google 雲端硬碟、日曆、文件、試算表和簡報 API 時不會直接收費。
不同 Google 產品的收費方式不同,請務必參閱 API 說明文件瞭解相關資訊。
摘要
您現在已瞭解如何啟用 Google API,請前往 API 管理工具,啟用 Cloud Translation API 和 App Engine 服務 (如果尚未啟用)。前者是因為應用程式會使用該服務,後者則是因為您要部署 App Engine 應用程式。如果您想透過命令列執行此操作,請改為發出以下指令:
gcloud services enable appengine.googleapis.com translate.googleapis.com
雖然「一律免費」等級的總結頁面未列出每月配額,但Translation API 的定價頁面指出,所有使用者每月可獲得固定數量的翻譯字元。如果您未超過此門檻,就不會產生任何 API 費用。如果還有其他 Google Cloud 相關費用,我們會在結尾的「清理」一節中討論。
4. 取得範例應用程式程式碼
在本機或 Cloud Shell 中複製存放區中的程式碼 (使用 git clone
指令),或是從綠色「Code」按鈕下載 ZIP 檔案,如以下螢幕截圖所示:
完成所有準備工作後,請建立資料夾的完整副本,以便進行這個教學課程,因為您可能需要刪除或變更檔案。如果您想進行不同的部署作業,可以複製原始檔案來重新開始,這樣就不必再次複製或下載。
5. 範例應用程式導覽
範例應用程式是簡單的 Google 翻譯衍生產品,可提示使用者輸入英文文字,並接收該文字的西班牙文對應翻譯。現在開啟 main.py
檔案,讓我們瞭解其運作方式。省略有關授權的註解行,頂端和底部會如下所示:
from flask import Flask, render_template, request
import google.auth
from google.cloud import translate
app = Flask(__name__)
_, PROJECT_ID = google.auth.default()
TRANSLATE = translate.TranslationServiceClient()
PARENT = 'projects/{}'.format(PROJECT_ID)
SOURCE, TARGET = ('en', 'English'), ('es', 'Spanish')
# . . . [translate() function definition] . . .
if __name__ == '__main__':
import os
app.run(debug=True, threaded=True, host='0.0.0.0',
port=int(os.environ.get('PORT', 8080)))
- 匯入內容會導入 Flask 功能、
google.auth
模組和 Cloud Translation API 用戶端程式庫。 - 全域變數代表 Flask 應用程式、Cloud 專案 ID、Translation API 用戶端、Translation API 呼叫的父項「位置路徑」,以及原文和譯文語言。在本例中,這些值分別是英文 (
en
) 和西班牙文 (es
),但您可以將這些值變更為 Cloud Translation API 支援的其他語言代碼。 - 底部的大型
if
區塊是在教學課程中用來在本機執行此應用程式,它會利用 Flask 開發伺服器提供應用程式服務。如果網路伺服器未內含在容器中,這裡也會提供 Cloud Run 部署教學課程。系統會要求您在容器中啟用伺服器的封裝作業,但如果您忽略這項操作,應用程式程式碼就會改為使用 Flask 開發伺服器。(這不是 App Engine 或 Cloud Functions 的問題,因為這些是來源平台,也就是說,Google Cloud 會提供並執行預設的網路伺服器)。
最後,在 main.py
中間是應用程式的核心,即 translate()
函式:
@app.route('/', methods=['GET', 'POST'])
def translate(gcf_request=None):
"""
main handler - show form and possibly previous translation
"""
# Flask Request object passed in for Cloud Functions
# (use gcf_request for GCF but flask.request otherwise)
local_request = gcf_request if gcf_request else request
# reset all variables (GET)
text = translated = None
# if there is data to process (POST)
if local_request.method == 'POST':
text = local_request.form['text']
data = {
'contents': [text],
'parent': PARENT,
'target_language_code': TARGET[0],
}
# handle older call for backwards-compatibility
try:
rsp = TRANSLATE.translate_text(request=data)
except TypeError:
rsp = TRANSLATE.translate_text(**data)
translated = rsp.translations[0].translated_text
# create context & render template
context = {
'orig': {'text': text, 'lc': SOURCE},
'trans': {'text': translated, 'lc': TARGET},
}
return render_template('index.html', **context)
主要函式會負責處理使用者輸入內容,並呼叫 Translation API 來執行繁重的工作。以下為你詳細說明:
- 請檢查是否有使用
local_request
變數的 Cloud Functions 傳送要求。Cloud Functions 會傳送自己的 Flask 要求物件,而其他所有要求 (在本機執行或部署至 App Engine 或 Cloud Run) 會直接從 Flask 取得要求物件。 - 重設表單的基本變數。這項功能主要適用於 GET 要求,因為 POST 要求會包含取代這些資料的資料。
- 如果是 POST,請擷取要翻譯的文字,並建立代表 API 中繼資料需求的 JSON 結構。然後呼叫 API,如果使用者採用較舊的程式庫,則會改用舊版 API。
- 無論如何,請將實際結果 (POST) 或無資料 (GET) 格式化至範本內容並進行算繪。
應用程式的視覺部分位於範本 index.html
檔案中。這項功能會顯示先前翻譯的結果 (如果沒有,則為空白),接著顯示表單,要求使用者輸入要翻譯的內容:
<!doctype html>
<html><head><title>My Google Translate 1990s</title><body>
<h2>My Google Translate (1990s edition)</h2>
{% if trans['text'] %}
<h4>Previous translation</h4>
<li><b>Original</b>: {{ orig['text'] }} (<i>{{ orig['lc'][0] }}</i>)</li>
<li><b>Translated</b>: {{ trans['text'] }} (<i>{{ trans['lc'][0] }}</i>)</li>
{% endif %}
<h4>Enter <i>{{ orig['lc'][1] }}</i> text to translate to <i>{{ trans['lc'][1] }}</i>:</h4>
<form method="POST"><input name="text"><input type="submit"></form>
</body></html>
6. 安裝本機套件/依附元件 (至 lib)
如先前所述,範例應用程式會使用 Flask 微型網路架構,以及 Python 適用的 Google Cloud Translation API 用戶端程式庫。使用此 pip
(或 pip3
) 指令安裝及更新 pip
以及這兩個套件:
pip install -t lib -r requirements.txt
執行上述註解後,您會看到安裝輸出內容,可能會像這樣:
$ pip install -t lib -r requirements.txt DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality. Collecting flask>=1.1.2 Using cached Flask-1.1.4-py2.py3-none-any.whl (94 kB) Collecting google-cloud-translate>=2.0.1 Using cached google_cloud_translate-2.0.2-py2.py3-none-any.whl (91 kB) Collecting click<8.0,>=5.1 Using cached click-7.1.2-py2.py3-none-any.whl (82 kB) Collecting Jinja2<3.0,>=2.10.1 Using cached Jinja2-2.11.3-py2.py3-none-any.whl (125 kB) Collecting Werkzeug<2.0,>=0.15 Using cached Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB) Collecting itsdangerous<2.0,>=0.24 Using cached itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB) Collecting google-api-core[grpc]<2.0.0dev,>=1.15.0 Downloading google_api_core-1.29.0-py2.py3-none-any.whl (93 kB) |████████████████████████████████| 93 kB 2.1 MB/s Collecting google-cloud-core<2.0dev,>=1.1.0 Using cached google_cloud_core-1.6.0-py2.py3-none-any.whl (28 kB) Collecting MarkupSafe>=0.23 Using cached MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl (17 kB) Collecting protobuf>=3.12.0 Downloading protobuf-3.17.2-cp27-cp27m-macosx_10_9_x86_64.whl (958 kB) |████████████████████████████████| 958 kB 21.6 MB/s Collecting futures>=3.2.0; python_version < "3.2" Using cached futures-3.3.0-py2-none-any.whl (16 kB) Collecting six>=1.13.0 Using cached six-1.16.0-py2.py3-none-any.whl (11 kB) Collecting packaging>=14.3 Using cached packaging-20.9-py2.py3-none-any.whl (40 kB) Collecting googleapis-common-protos<2.0dev,>=1.6.0 Using cached googleapis_common_protos-1.52.0-py2.py3-none-any.whl (100 kB) Collecting requests<3.0.0dev,>=2.18.0 Using cached requests-2.25.1-py2.py3-none-any.whl (61 kB) Collecting google-auth<2.0dev,>=1.25.0 Using cached google_auth-1.30.1-py2.py3-none-any.whl (146 kB) Collecting pytz Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB) Collecting setuptools>=40.3.0 Using cached setuptools-44.1.1-py2.py3-none-any.whl (583 kB) Collecting grpcio<2.0dev,>=1.29.0; extra == "grpc" Using cached grpcio-1.38.0-cp27-cp27m-macosx_10_10_x86_64.whl (3.8 MB) Collecting pyparsing>=2.0.2 Using cached pyparsing-2.4.7-py2.py3-none-any.whl (67 kB) Collecting chardet<5,>=3.0.2 Using cached chardet-4.0.0-py2.py3-none-any.whl (178 kB) Collecting urllib3<1.27,>=1.21.1 Using cached urllib3-1.26.5-py2.py3-none-any.whl (138 kB) Collecting idna<3,>=2.5 Using cached idna-2.10-py2.py3-none-any.whl (58 kB) Collecting certifi>=2017.4.17 Downloading certifi-2021.5.30-py2.py3-none-any.whl (145 kB) |████████████████████████████████| 145 kB 61.1 MB/s Collecting pyasn1-modules>=0.2.1 Using cached pyasn1_modules-0.2.8-py2.py3-none-any.whl (155 kB) Collecting rsa<4.6; python_version < "3.6" Using cached rsa-4.5-py2.py3-none-any.whl (36 kB) Collecting cachetools<5.0,>=2.0.0 Using cached cachetools-3.1.1-py2.py3-none-any.whl (11 kB) Collecting enum34>=1.0.4; python_version < "3.4" Using cached enum34-1.1.10-py2-none-any.whl (11 kB) Collecting pyasn1<0.5.0,>=0.4.6 Using cached pyasn1-0.4.8-py2.py3-none-any.whl (77 kB) Installing collected packages: click, MarkupSafe, Jinja2, Werkzeug, itsdangerous, flask, six, protobuf, futures, pyparsing, packaging, googleapis-common-protos, chardet, urllib3, idna, certifi, requests, pyasn1, pyasn1-modules, rsa, cachetools, setuptools, google-auth, pytz, enum34, grpcio, google-api-core, google-cloud-core, google-cloud-translate ERROR: pip's legacy dependency resolver does not consider dependency conflicts when selecting packages. This behaviour is the source of the following dependency conflicts. matplotlib 1.3.1 requires nose, which is not installed. matplotlib 1.3.1 requires tornado, which is not installed. Successfully installed Jinja2-2.11.3 MarkupSafe-1.1.1 Werkzeug-1.0.1 cachetools-3.1.1 certifi-2021.5.30 chardet-4.0.0 click-7.1.2 enum34-1.1.10 flask-1.1.4 futures-3.3.0 google-api-core-1.29.0 google-auth-1.30.1 google-cloud-core-1.6.0 google-cloud-translate-2.0.2 googleapis-common-protos-1.52.0 grpcio-1.38.0 idna-2.10 itsdangerous-1.1.0 packaging-20.9 protobuf-3.17.2 pyasn1-0.4.8 pyasn1-modules-0.2.8 pyparsing-2.4.7 pytz-2021.1 requests-2.25.1 rsa-4.5 setuptools-44.1.1 six-1.16.0 urllib3-1.26.5
7. 部署服務
如要將翻譯服務部署至 Python 2 App Engine,請執行下列指令:
gcloud app deploy
輸出內容應如下所示,並提供一些提示,說明後續步驟:
$ gcloud app deploy Services to deploy: descriptor: [/private/tmp/nebulous-serverless-python/app.yaml] source: [/private/tmp/nebulous-serverless-python] target project: [PROJECT_ID] target service: [default] target version: [20210422t161025] target url: [https://PROJECT_ID.appspot.com] Do you want to continue (Y/n)? Beginning deployment of service [default]... ╔════════════════════════════════════════════════════════════╗ ╠═ Uploading 1290 files to Google Cloud Storage ═╣ ╚════════════════════════════════════════════════════════════╝ File upload done. Updating service [default]...done. Setting traffic split for service [default]...done. Deployed service [default] to [https://PROJECT_ID.appspot.com] You can stream logs from the command line by running: $ gcloud app logs tail -s default To view your application in the web browser run: $ gcloud app browse
您的應用程式現在已在全球推出,您應該可以透過部署輸出內容中提供的網址 (包含專案 ID) 存取應用程式:
翻譯內容即可體驗!
8. 結語
恭喜!您已瞭解如何啟用 Cloud Translation API、取得必要的憑證,以及將簡易的網頁應用程式部署至 Python 2 App Engine!如要進一步瞭解這項部署作業,請參閱這個存放區中的表格。
清除所用資源
使用 Cloud Translation API 時,您可以每月免費翻譯固定字元數量。App Engine 也設有免費配額,Cloud Functions 和 Cloud Run 也是如此。如有超出,系統會向您收取費用。如果您打算繼續進行下一個程式碼研究室,則不必關閉應用程式。
不過,如果您還不想繼續進行下一篇教學課程,或是擔心網路會偵測到您剛部署的應用程式,請停用 App Engine 應用程式、刪除 Cloud Function,或是停用 Cloud Run 服務,以免產生費用。當您準備繼續進行下一個程式碼研究室時,可以重新啟用該研究室。另一方面,如果您不打算繼續使用這個應用程式或其他程式碼研究室,且想要完全刪除所有內容,可以關閉專案。
此外,部署至 Google Cloud 無伺服器運算平台也會產生少許建構和儲存費用。Cloud Build 和 Cloud Storage 一樣,都有各自的免費配額。為提供更高的透明度,Cloud Build 會建構應用程式映像檔,然後儲存在 Cloud Container Registry 或其後繼服務 Artifact Registry 中。該圖片的儲存空間會使用部分配額,而將圖片傳輸至服務時,網路傳出也會使用部分配額。不過,您所在的區域可能沒有免付費層級,因此請注意儲存空間用量,盡量降低可能產生的費用。
9. 其他資源
在後續章節中,您可以找到其他閱讀材料和建議練習,進一步加深您在本教學課程中所學到的知識。
其他研究
您現在已對 Translation API 有些許認識,接下來我們將進行一些額外的練習,進一步提升您的技能。如要繼續學習,請修改範例應用程式,執行下列操作:
- 完成本程式碼研究室的所有其他版本,以便在本機上執行或部署至 Google Cloud 無伺服器運算平台 (請參閱 存放區 README)。
- 使用其他程式設計語言完成本教學課程。
- 變更這個應用程式,以支援不同的原文或譯文語言。
- 升級此應用程式,以便將文字翻譯成多種語言;變更範本檔案,讓下拉式選單顯示支援的目標語言。
瞭解詳情
Google App Engine
- App Engine 首頁
- App Engine 說明文件
- Python 3 App Engine 快速入門
- App Engine 的預設服務帳戶
- Python 2 App Engine (標準) 執行階段
- Python 3 App Engine (標準) 執行階段
- Python 2 與 3 App Engine (標準) 執行階段的差異
- 從 Python 2 遷移至 Python 3 的 App Engine (標準) 遷移指南
Google Cloud Functions
Google Cloud Run
Google Cloud Buildpacks、Container Registry、Artifact Registry
- Cloud Buildpacks 發布公告
- Cloud Buildpacks 存放區
- Cloud Artifact Registry 首頁
- Cloud Artifact Registry 說明文件
- Cloud Container Registry 首頁
- Cloud Container Registry 說明文件
Google Cloud Translation 和 Google ML Kit
- Cloud Translation 首頁
- Cloud Translation 說明文件
- Translation API 定價頁面
- 所有 Cloud AI/ML「構建區塊」API
- Google ML Kit (行動裝置專用的雲端 AI/機器學習 API 子集)
- Google ML Kit Translation API
其他 Google Cloud 產品/頁面
Python 和 Flask
授權
本教學課程採用 Creative Commons Attribution 2.0 Generic License 授權,而存放區中的原始碼則採用 Apache 2 授權。