部署基本 ";Google 翻譯"Python 2 App Engine 上的應用程式

1. 總覽

這個系列的程式碼研究室 (循序漸進的實作教學課程) 旨在協助開發人員瞭解部署應用程式時有哪些不同的選項。在本程式碼研究室中,您將瞭解如何使用 Python 搭配 Google Cloud Translation API,並在本機執行或部署至 Cloud 無伺服器運算平台 (App Engine、Cloud Functions 或 Cloud Run)。您可以透過本教學課程的存放區中的範例應用程式部署 (至少)「八」種不同的方法,而只需要變更細微的設定變更:

  1. 本機 Flask 伺服器 (Python 2)
  2. 本機 Flask 伺服器 (Python 3)
  3. App Engine (Python 2)
  4. App Engine (Python 3)
  5. Cloud Functions (Python 3)
  6. Cloud Run (透過 Docker 執行 Python 2)
  7. Cloud Run (透過 Docker 執行 Python 3)
  8. Cloud Run (透過 Cloud Buildpacks 執行 Python 3)

本程式碼研究室著重於將應用程式部署至上述粗體的平台。

你將瞭解如何

軟硬體需求

問卷調查

您會如何使用這個教學課程?

閱讀並完成練習 唯讀

您對 Python 的使用體驗有何評價?

新手 中級 還算容易

針對使用 Google Cloud 服務的經驗,您會給予什麼評價?

新手 中級 還算容易

2. 設定和需求

自修環境設定

  1. 登入 Google Cloud 控制台,建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • 「專案名稱」是這項專案參與者的顯示名稱。這是 Google API 不使用的字元字串,您可以隨時更新。
  • 所有 Google Cloud 專案的專案 ID 均不得重複,且設定後即無法變更。Cloud 控制台會自動產生一個不重複的字串。但通常是在乎它何在在大部分的程式碼研究室中,您必須參照專案 ID (通常稱為 PROJECT_ID),因此如果您不喜歡的話,請隨機產生一個,或者,您也可以自行嘗試看看是否可用。是「凍結」建立專案後
  • 還有第三個值,也就是部分 API 使用的專案編號。如要進一步瞭解這三個值,請參閱說明文件
  1. 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Cloud 資源/API。執行這個程式碼研究室並不會產生任何費用,如果有的話。如要關閉資源,以免產生本教學課程結束後產生的費用,請按照任「清除所用資源」操作請參閱本程式碼研究室結尾處的操作說明。Google Cloud 的新使用者符合 $300 美元免費試用計畫的資格。

3. 啟用 Translation API

在範例應用程式中,您必須改為按照以下類似操作說明,啟用 Cloud Translation APIApp 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 控制台

您也可以在 API 管理員中啟用 Vision API。在 Cloud 控制台中,前往「API 管理員」,然後選取「程式庫」

fb0f1d315f122d4a.png

如要啟用 Cloud Vision API,請開始輸入「vision」,且任何符合您目前輸入字詞的內容便會顯示:

2275786a24f8f204.png

選取要啟用的 API,然後按一下「啟用」

2556f923b628e31.png

費用

雖然許多 Google API 都能在不收費的情況下使用,但可使用 Google Cloud 產品,API「不」免費。啟用 Cloud API 時,系統可能會要求您提供有效的帳單帳戶。不過請注意,部分 Google Cloud 產品提供「一律免費」級別 (每日/每月),您必須超過這個額度才能產生帳單費用;否則系統不會向您的信用卡 (或指定付款方式) 收費。

啟用 API 前,使用者應先查看該 API 的定價資訊,特別是是否提供免費方案,以及 API 的內容為何。如果已啟用 Cloud Vision API,請查看定價資訊頁面。Cloud Vision 沒有免費配額,只要不超過匯總用量上限 (每月以內) 使用,就不會產生任何費用。

定價和免費方案會因 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 檔案,如以下螢幕截圖所示:

5cd6110c4414cf65.png

您現在已擁有所有內容,請建立資料夾的完整副本來進行教學課程,因為您可能需要刪除或變更檔案。如需執行其他部署作業,您可以直接複製原始檔案,不必複製或重新下載。

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)))
  1. 匯入作業內含 Flask 功能、google.auth 模組和 Cloud Translation API 用戶端程式庫。
  2. 全域變數代表 Flask 應用程式、Cloud 專案 ID、Translation API 用戶端、父項「位置路徑」,以及原文和譯文語言。在本例中為英文 (en) 和西班牙文 (es),但您可以將這些值變更為 Cloud Translation API 支援的其他語言
  3. 底部的大型 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 來執行繁重工作。以下將詳細說明:

  1. 使用 local_request 變數檢查要求是否來自 Cloud Functions。Cloud Functions 會使用自己的 Flask 要求物件傳送,而其他所有 (在本機執行或部署至 App Engine 或 Cloud Run) 都會直接從 Flask 取得要求物件。
  2. 重設表單的基本變數。這主要用於 GET 要求,因為 POST 要求會有資料取代這些要求。
  3. 如果是 POST,請擷取要翻譯的文字,然後建立代表 API 中繼資料規定的 JSON 結構。然後呼叫 API,如果使用者使用的是舊版程式庫,請改回先前的 API 版本。
  4. 無論如何,將實際結果 (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) 存取應用程式:

da28f951c33a2c3d.png

趕快翻譯,看看成效如何!

d911984d15dd5ef9.png

8. 結語

恭喜!您已瞭解如何啟用 Cloud Translation API、取得必要憑證,並將簡單的網頁應用程式部署至 Python 2 App Engine!如要進一步瞭解這個部署作業,請參閱存放區中的這個表格

清除所用資源

Cloud Translation API 可讓您每月免費處理固定數量的翻譯字元。App Engine 也提供免費配額Cloud FunctionsCloud Run 也是如此。超過上述任一額度時,就必須支付費用。如果您打算繼續下一個程式碼研究室,則不必關閉應用程式。

但是,如果您還沒準備好進行下一個教學課程,或擔心網際網路發現您剛剛部署的應用程式,請停用 App Engine 應用程式刪除 Cloud 函式停用 Cloud Run 服務,以免產生費用。當您準備好前往下一個程式碼研究室時,即可重新啟用。另一方面,如果您不打算繼續使用這個應用程式或其他程式碼研究室,且想要徹底刪除所有內容,可以關閉專案

此外,部署至 Google Cloud 無伺服器運算平台會產生少許建構和儲存空間費用Cloud Build 提供的免費配額與 Cloud Storage 相同。為提升資訊透明度,Cloud Build 會建構應用程式映像檔,並將映像檔儲存在其後續的 Cloud Container RegistryArtifact Registry 中。這個映像檔的儲存空間會佔用部分配額,如同網路輸出圖片傳輸至服務一般。不過,您可能居住的區域沒有這類免費方案,因此請留意儲存空間用量,盡可能降低潛在費用。

9. 其他資源

以下各節提供其他閱讀素材和推薦練習,有助您增強完成本教學課程後獲得的知識。

其他研究

您已經瞭解過 Translation API 的經驗,現在讓我們進行一些額外的練習,進一步培養您的技能。如要繼續學習路徑,請修改範例應用程式,執行下列操作:

  1. 完成本程式碼研究室的所有其他版本,以便在本機執行或部署至 Google Cloud 無伺服器運算平台 (請參閱存放區 README)。
  2. 使用其他程式設計語言完成教學課程。
  3. 變更這個應用程式,支援不同的原文或譯文語言。
  4. 升級這個應用程式後,即可將文字翻譯成多種語言。變更範本檔案,加入支援的目標語言下拉式選單。

瞭解詳情

Google App Engine

Google Cloud Functions

Google Cloud Run

Google Cloud Buildpacks、Container Registry、Artifact Registry

Google Cloud Translation 和 Google ML 套件

其他 Google Cloud 產品/頁面

Python 和 Flask

授權

本教學課程採用的是創用 CC 姓名標示 2.0 通用授權,而存放區中的原始碼是依據 Apache 2 授權。