Skip to content

Latest commit

 

History

History
 
 

python

Nebulous serverless Cloud Translation API app

💥 Jan 2024 update
Python 2.7 apps can no longer be deployed on App Engine. Either upgrade to 3.8+ or migrate your app to Cloud Run or other platform that still supports Python 2. More information is available in the "What you need to know" deprecation post.

Python (2 and 3) version

While the majority of this app's deployments are in Python 3, there are still users upgrading from Python 2, so our Python 2 code is meant to help with migration & planning. Admittedly, there may seem to be a bit of "cheating" due to the duplicity of Python 2 and 3, especially since the application is compatible across both language versions without modification or use of compatibility libraries. However there are significant differences between Python 2 and 3 deployment requirements irregardless of language differences. Additional notes:

  • For local or Cloud Run deployments, there are little/no updates to go from Python 2 to 3.
  • Neither Cloud Functions nor Cloud Run with Cloud Buildpacks support Python 2.
  • There is also an equivalent Node.js version of this app.

Codelab links

Deployment Python 2 Python 3
Local/hosted Flask codelab same as Python 2
App Engine codelab codelab
Cloud Functions N/A codelab
Cloud Run (Docker) codelab codelab
Cloud Run (Buildpacks) N/A codelab

^ — not recommended as of Jan 2024 as developers can no longer deploy Python 2 apps to App Engine (see sidebar above)

Deployments and their files

These are the files provided in this repo and the deployments they're applicable to:

repository files

NOTES:

    • requirements.txt is used for local and App Engine (2.x) package installations and not required in deployments themselves unlike all others
  • main.py and templates/index.html comprise the entire application and are always required
  • noxfile.py and test_translate.py are for testing only; see Testing section below
  • All .*ignore and .git* files/folders are administrative and not listed in table above or deployments below
  • Files applicable only to a specific language version are annotated above

Below are the required settings and instructions for all documented deployments. The "TL:DR;" section at the top of each configuration summarizes the key files (see above) while the table beneath spells out the details. No administrative files are listed.

NOTE: Serverless deployments (as configured here) use default service accounts which provide a broad set of permissions to assist you in getting a working prototype. When preparing to launch to production, the Google Cloud team recommends the best practice of "least privileges," and instead use user-managed service accounts with the minimal set of permissions allowing your app to function properly.

Local Flask server (Python 2)

TL;DR: application files (main.py & requirements.txt)

File Description
main.py use as-is from repo
app.yaml unused (delete or leave as-is)
appengine_config.py unused (delete)
requirements.txt use as-is to install packages locally (see below) but unused thereafter
lib unused (delete or leave as-is if it exists)
Dockerfile unused (delete or leave as-is)
Procfile unused (delete or leave as-is)

Instructions:

  1. Run pip install -U pip -r requirements.txt to install/update packages locally (or pip2)
  2. Run gcloud auth application-default login to set your credentials
  3. Run python main.py to run on local Flask server (or python2)

Local Flask server (Python 3)

TL;DR: app files (identical to Python 2 deployment)

File Description
main.py use as-is from repo
app.yaml unused (delete or leave as-is)
appengine_config.py unused (delete)
requirements.txt use as-is to install packages locally (see below) but unused thereafter
lib unused (delete or leave as-is if it exists)
Dockerfile unused (delete or leave as-is)
Procfile unused (delete or leave as-is)

Instructions:

  1. Run pip install -U pip -r requirements.txt to install/update packages locally (or pip3)
  2. Run gcloud auth application-default login to set your credentials
  3. Run python main.py to run on local Flask server (or python3)

App Engine (Python 2)

NOTE: apps can no longer be deployed to Python 2 GAE; this section is left for historical purposes.

TL;DR: app files plus app.yaml, appengine_config.py, and lib

File Description
main.py use as-is from repo
app.yaml use as-is from repo (ensure #runtime:python312 commented out)
appengine_config.py use as-is from repo
requirements.txt use as-is to install packages locally (see below) but unused thereafter
lib create folder per instructions below
Dockerfile unused (delete or leave as-is)
Procfile unused (delete or leave as-is)

Instructions:

  1. Run pip install -t lib -r requirements.txt to populate lib folder (or pip2)
  2. Run gcloud app deploy to deploy to Python 2 App Engine
    • You'll be prompted for the REGION if deploying to App Engine the first time.
    • App Engine apps are tied to one region, so it can't be changed once it's set, meaning you won't be prompted thereafter.

App Engine (Python 3)

TL;DR: app files plus app.yaml

File Description
main.py use as-is from repo
app.yaml uncomment runtime:python312 (or Python 3.8-3.12); delete all other lines
appengine_config.py unused (delete)
requirements.txt use as-is from repo
lib delete (or rename) this folder if it exists (not used with Python 3 App Engine)
Dockerfile unused (delete or leave as-is)
Procfile unused (delete or leave as-is)

Instructions:

  1. Edit app.yaml (see above)
  2. (optional) Delete app.yaml, lib and appengine_config.py (unused)
  3. Run gcloud app deploy to deploy to Python 3 App Engine
    • You'll be prompted for the REGION if deploying to App Engine the first time.
    • App Engine apps are tied to one region, so it can't be changed once it's set, meaning you won't be prompted thereafter.

Cloud Functions (Python 3)

TL;DR: app files

File Description
main.py use as-is from repo
app.yaml unused (delete or leave as-is; only for App Engine)
appengine_config.py unused (delete)
requirements.txt use as-is from repo
lib delete (or rename) this folder if it exists (not used with Cloud Functions)
Dockerfile unused (delete or leave as-is)
Procfile unused (delete or leave as-is)

Instructions:

  1. (optional) Delete app.yaml, lib and appengine_config.py (unused)
  2. Run gcloud functions deploy translate --runtime python312 --trigger-http --allow-unauthenticated to deploy to Cloud Functions (or Python 3.8-3.12)
    • That command creates & deploys a new HTTP-triggered Cloud Function (name must match what's in main.py)
    • You'll be prompted for the REGION if deploying a Cloud Function the first time.
    • Cloud Functions can be deployed to different regions within a project, but once the region has been set for a function, it cannot be changed.
  3. There is no support for Python 2 with Cloud Functions

Cloud Run (Python 2 via Docker)

TL;DR: app files plus Dockerfile

File Description
main.py use as-is from repo
app.yaml unused (delete or leave as-is; only for App Engine)
appengine_config.py unused (delete)
requirements.txt grpcio<1.40.0 applies to this deployment
lib delete (or rename) this folder if it exists (not used with Cloud Run)
Dockerfile use as-is from repo (ensure #FROM python:3-slim commented out)
Procfile unused (delete or leave as-is)

Instructions:

  1. (optional) Delete app.yaml, lib and appengine_config.py (unused)
  2. Run gcloud run deploy translate --allow-unauthenticated --platform managed to deploy to Cloud Run
    • The above command wraps docker build and docker push, deploying the image to Cloud Artifact Registry (must be enabled), and finally docker run to deploy the service, all in one convenient command.
    • You'll be prompted to provide a REGION unless you also add --region REGION on the cmd-line
    • You'll be prompted to provide a SOURCE folder unless you also add --source FOLDER, e.g., --source . on the cmd-line
    • Supplying both --region and --source options provide a fully non-interactive deploy (unless you don't have a repository, in which case you'll be prompted to create one)
  3. You can also use this shortcut to deploy to Cloud Run: Run on Google Cloud
  4. By default, App Engine & Cloud Functions launch production servers; with Cloud Run, the Flask development server is used for prototyping. For production, bundle and deploy a production server like gunicorn:
    1. Uncomment gunicorn from requirements.txt (commented out for App Engine & Cloud Functions)
    2. Uncomment the ENTRYPOINT entry for gunicorn replacing the default entry in Dockerfile
    3. Re-use the same deploy command

Cloud Run (Python 3 via Docker)

TL;DR: app files plus Dockerfile (nearly identical to Python 2 deployment)

File Description
main.py use as-is from repo
app.yaml unused (delete or leave as-is; only for App Engine)
appengine_config.py unused (delete)
requirements.txt use as-is from repo
lib delete (or rename) this folder if it exists (not used with Cloud Run)
Dockerfile replace FROM python:2-slim with FROM python:3-slim (commented out) but keep all other lines
Procfile unused (delete or leave as-is)

Instructions:

  1. (optional) Delete app.yaml, lib and appengine_config.py (unused)
  2. Edit Dockerfile (see above)
  3. Run gcloud run deploy translate --allow-unauthenticated --platform managed to deploy to Cloud Run
    • The above command wraps docker build and docker push, deploying the image to Cloud Artifact Registry (must be enabled), and finally docker run to deploy the service, all in one convenient command.
    • You'll be prompted to provide a REGION unless you also add --region REGION on the cmd-line
    • You'll be prompted to provide a SOURCE folder unless you also add --source FOLDER, e.g., --source . on the cmd-line
    • Supplying both --region and --source options provide a fully non-interactive deploy (unless you don't have a repository, in which case you'll be prompted to create one)
  4. The shortcut "button" above can be customized for Python 3 if you make the Dockerfile update above and commit it to your fork/clone.
  5. By default, App Engine & Cloud Functions launch production servers; with Cloud Run, the Flask development server is used for prototyping. For production, bundle and deploy a production server like gunicorn:
    1. Uncomment gunicorn from requirements.txt (commented out for App Engine & Cloud Functions)
    2. Uncomment the ENTRYPOINT entry for gunicorn replacing the default entry in Dockerfile
    3. Re-use the same deploy command

Cloud Run (Python 3 via Cloud Buildpacks)

TL;DR: app files plus Procfile

File Description
main.py use as-is from repo
app.yaml unused (delete or leave as-is; only for App Engine)
appengine_config.py unused (delete)
requirements.txt use as-is from repo
lib delete (or rename) this folder if it exists (not used with Cloud Run)
Dockerfile delete (or rename) this file (required)
Procfile use as-is from repo

Instructions:

  1. (optional) Delete app.yaml, lib and appengine_config.py (unused)
  2. Delete Dockerfile (or rename it)
    • There is no support for Python 2 with Cloud Buildpacks (2.x developers must use Docker)
  3. Run gcloud run deploy translate --allow-unauthenticated --platform managed to deploy to Cloud Run
    • The above command wraps docker build and docker push, deploying the image to Cloud Artifact Registry (must be enabled), and finally docker run to deploy the service, all in one convenient command.
    • You'll be prompted to provide a REGION unless you also add --region REGION on the cmd-line
    • You'll be prompted to provide a SOURCE folder unless you also add --source FOLDER, e.g., --source . on the cmd-line
    • Supplying both --region and --source options provide a fully non-interactive deploy (unless you don't have a repository, in which case you'll be prompted to create one)
  4. By default, App Engine & Cloud Functions launch production servers; with Cloud Run, the Flask development server is used for prototyping. For production, bundle and deploy a production server like gunicorn:
    1. Uncomment gunicorn from requirements.txt (commented out for App Engine & Cloud Functions)
    2. Uncomment the web: entry for gunicorn replacing the default entry in Procfile
    3. Re-use the same deploy command

References

These are relevant links only to the app in this folder (for all others, see the README one level up:

Testing

Testing is driven by nox which uses pytest for testing and flake8 for linting, installing both in virtual environments along with application dependencies, flask and google-cloud-translate, and finally, blinker, a signaling framework integrated into Flask. To run the lint and unit tests (testing GET and POST requests), install nox (with the expected pip install -U nox) and run it from the command line in the application folder and ensuring noxfile.py is present.

Expected output

$ nox
nox > Running session tests-2.7
nox > Creating virtual environment (virtualenv) using python2.7 in .nox/tests-2-7
nox > python -m pip install pytest blinker flask google-cloud-translate
nox > pytest
============================================ test session starts =============================================
platform darwin -- Python 2.7.16, pytest-4.6.11, py-1.10.0, pluggy-0.13.1
rootdir: /private/tmp/cloud-nebulous-serverless-python
collected 2 items

test_translate.py ..                                                                                   [100%]

============================================== warnings summary ==============================================
.nox/tests-2-7/lib/python2.7/site-packages/google/cloud/translate_v3/__init__.py:32
  /private/tmp/cloud-nebulous-serverless-python/.nox/tests-2-7/lib/python2.7/site-packages/google/cloud/translate_v3/__init__.py:32: DeprecationWarning: A future version of this library will drop support for Python 2.7. More details about Python 2 support for Google Cloud Client Libraries can be found at https://cloud.google.com/python/docs/python2-sunset/
    warnings.warn(message, DeprecationWarning)

-- Docs: https://docs.pytest.org/en/latest/warnings.html
==================================== 2 passed, 1 warnings in 1.02 seconds ====================================
nox > Session tests-2.7 was successful.
nox > Running session tests-3.6
nox > Creating virtual environment (virtualenv) using python3.6 in .nox/tests-3-6
nox > python -m pip install pytest blinker flask google-cloud-translate
nox > pytest
============================================ test session starts =============================================
platform darwin -- Python 3.6.8, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /private/tmp/cloud-nebulous-serverless-python
collected 2 items

test_translate.py ..                                                                                   [100%]

============================================= 2 passed in 1.22s ==============================================
nox > Session tests-3.6 was successful.
nox > Running session tests-3.9
nox > Creating virtual environment (virtualenv) using python3.9 in .nox/tests-3-9
nox > python -m pip install pytest blinker flask google-cloud-translate
nox > pytest
============================================ test session starts =============================================
platform darwin -- Python 3.9.1, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /private/tmp/cloud-nebulous-serverless-python
collected 2 items

test_translate.py ..                                                                                   [100%]

============================================= 2 passed in 1.04s ==============================================
nox > Session tests-3.9 was successful.
nox > Running session lint-2.7
nox > Creating virtual environment (virtualenv) using python2.7 in .nox/lint-2-7
nox > python -m pip install flake8
nox > flake8 --show-source --builtin=gettext --max-complexity=20 --exclude=.nox,.cache,env,lib,generated_pb2,*_pb2.py,*_pb2_grpc.py --ignore=E121,E123,E126,E203,E226,E24,E266,E501,E704,W503,W504,I202 --max-line-length=88 .
nox > Session lint-2.7 was successful.
nox > Running session lint-3.6
nox > Creating virtual environment (virtualenv) using python3.6 in .nox/lint-3-6
nox > python -m pip install flake8
nox > flake8 --show-source --builtin=gettext --max-complexity=20 --exclude=.nox,.cache,env,lib,generated_pb2,*_pb2.py,*_pb2_grpc.py --ignore=E121,E123,E126,E203,E226,E24,E266,E501,E704,W503,W504,I202 --max-line-length=88 .
nox > Session lint-3.6 was successful.
nox > Running session lint-3.9
nox > Creating virtual environment (virtualenv) using python3.9 in .nox/lint-3-9
nox > python -m pip install flake8
nox > flake8 --show-source --builtin=gettext --max-complexity=20 --exclude=.nox,.cache,env,lib,generated_pb2,*_pb2.py,*_pb2_grpc.py --ignore=E121,E123,E126,E203,E226,E24,E266,E501,E704,W503,W504,I202 --max-line-length=88 .
nox > Session lint-3.9 was successful.
nox > Ran multiple sessions:
nox > * tests-2.7: success
nox > * tests-3.6: success
nox > * tests-3.9: success
nox > * lint-2.7: success
nox > * lint-3.6: success
nox > * lint-3.9: success