1. Descripción general
Esta serie de codelabs (instructivos prácticos de autoaprendizaje) tiene como objetivo ayudar a los desarrolladores a comprender las diversas opciones que tienen a la hora de implementar sus aplicaciones. En este codelab, aprenderás a usar la API de Google Cloud Translation con Python y a ejecutarla de forma local o a implementarla en una plataforma de computación sin servidores de Cloud (App Engine, Cloud Functions o Cloud Run). La app de ejemplo que se encuentra en el repositorio de este instructivo se puede implementar (al menos) de ocho maneras diferentes con solo cambios de configuración menores:
- Servidor de Flask local (Python 2)
- Servidor de Flask local (Python 3)
- App Engine (Python 2)
- App Engine (Python 3)
- Cloud Functions (Python 3)
- Cloud Run (Python 2 a través de Docker)
- Cloud Run (Python 3 a través de Docker)
- Cloud Run (Python 3 a través de Cloud Buildpacks)
Este codelab se enfoca en la implementación de esta app en las plataformas en negrita mencionadas anteriormente.
Obtendrás información para hacer las siguientes acciones
- Usar las APIs de Google Cloud, específicamente la API de Cloud Translation (advanced/v3)
- Ejecuta una aplicación web básica de forma local o impleméntala en una plataforma de procesamiento sin servidores en la nube.
Requisitos
- Un proyecto de Google Cloud con una cuenta de Facturación de Cloud activa
- Flask instalado para ejecutarse de forma local o una plataforma de procesamiento sin servidores en la nube habilitada para implementaciones basadas en la nube
- Habilidades básicas de Python
- Tener conocimiento práctico de los comandos básicos del sistema operativo
Encuesta
¿Cómo usarás este instructivo?
¿Cómo calificarías tu experiencia en Python?
¿Cómo calificarías tu experiencia en el uso de los servicios de Google Cloud?
2. Configuración y requisitos
Configuración del entorno de autoaprendizaje
- Accede a Google Cloud Console y crea un proyecto nuevo o reutiliza uno existente. Si aún no tienes una cuenta de Gmail o de Google Workspace, debes crear una.
- El Nombre del proyecto es el nombre visible de los participantes de este proyecto. Es una string de caracteres que no se utiliza en las API de Google y se puede actualizar en cualquier momento.
- El ID del proyecto debe ser único en todos los proyectos de Google Cloud y es inmutable (no se puede cambiar después de configurarlo). Cloud Console genera automáticamente una string única, que, por lo general, no importa cuál sea. En la mayoría de los codelabs, debes hacer referencia al ID del proyecto (suele ser
PROJECT_ID
). Por lo tanto, si no te gusta, genera otro aleatorio o prueba con uno propio y comprueba si está disponible. Después de crear el proyecto, este ID se “congela” y no se puede cambiar. - Además, hay un tercer valor, el Número de proyecto, que usan algunas API. Obtén más información sobre estos tres valores en la documentación.
- A continuación, deberás habilitar la facturación en Cloud Console para usar las API o los recursos de Cloud. Ejecutar este codelab no debería costar mucho, tal vez nada. Si quieres cerrar los recursos para no se te facture más allá de este instructivo, sigue las instrucciones de “limpieza” que se encuentran al final del codelab. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de USD 300.
3. Habilitar la API de Translation
Para nuestra aplicación de muestra, habilitarás la API de Cloud Translation y el servicio de App Engine en su lugar mediante instrucciones similares que se proporcionan a continuación.
Habilita las APIs de Cloud
Introducción
Independientemente de la API de Google que desees usar en tu aplicación, estas deben estar habilitadas. En el siguiente ejemplo, se muestran dos formas de habilitar la API de Cloud Vision. Después de aprender a habilitar una API de Cloud, podrás habilitar otras APIs, ya que el proceso es similar.
Opción 1: En Cloud Shell o en la interfaz de línea de comandos
Si bien habilitar las APIs desde la consola de Cloud es más común, algunos desarrolladores prefieren hacer todo desde la línea de comandos. Para ello, debes buscar el “nombre de servicio” de una API. Parece una URL: SERVICE_NAME
.googleapis.com
. Puedes encontrarlos en el gráfico de productos admitidos o puedes buscarlos de manera programática con la API de Google Discovery.
Con esta información, puedes habilitar una API de la siguiente manera si usas Cloud Shell (o tu entorno de desarrollo local con la herramienta de línea de comandos de gcloud
instalada):
gcloud services enable SERVICE_NAME.googleapis.com
Por ejemplo, este comando habilita la API de Cloud Vision:
gcloud services enable vision.googleapis.com
Este comando habilita App Engine:
gcloud services enable appengine.googleapis.com
También puedes habilitar varias APIs con una solicitud. Por ejemplo, esta línea de comandos habilita Cloud Run, Cloud Artifact Registry y la API de Cloud Translation:
gcloud services enable artifactregistry.googleapis.com run.googleapis.com translate.googleapis.com
Opción 2: En la consola de Cloud
También puedes habilitar la API de Vision en el Administrador de API. En la consola de Cloud, ve al Administrador de API y selecciona Biblioteca.
Si quieres habilitar la API de Cloud Vision, comienza a escribir “vision”. en la barra de búsqueda, se mostrarán todos los elementos que coincidan con lo que ingresaste:
Selecciona la API que quieres habilitar y haz clic en Habilitar:
Costo
Si bien muchas APIs de Google se pueden usar sin tarifas, el uso de los productos de Google Cloud y Las APIs no son gratuitas. Cuando habilites las APIs de Cloud, es posible que se te solicite una cuenta de facturación activa. Sin embargo, es importante tener en cuenta que algunos productos de Google Cloud cuentan con la función “Siempre gratuito” (diario o mensual), que deberás superar para generar cargos de facturación De lo contrario, no se realizará el cargo en tu tarjeta de crédito (o el instrumento de facturación especificado).
Los usuarios deben hacer referencia a la información de precios de cualquier API antes de habilitarla, en especial si tienen un nivel gratuito y, de ser así, qué es. Si estuvieras habilitando la API de Cloud Vision, consultarías la página de información de precios. Cloud Vision tiene una cuota gratuita y, si te mantienes dentro de los límites agregados (dentro de cada mes), no debes incurrir en cargos.
Los precios y los niveles gratuitos varían entre las APIs de Google. Ejemplos:
- Google Cloud/GCP: Cada producto se factura de manera diferente y, por lo general, se paga por ciclo de CPU virtual, consumidor de almacenamiento, uso de memoria o pago por uso. consulta la información del nivel gratuito más arriba.
- Google Maps: Presenta un paquete de APIs y ofrece a los usuarios un crédito mensual gratuito de USD 200.
- APIs de Google Workspace (anteriormente G Suite): Ofrece uso gratuito (hasta ciertos límites) cubierto por una tarifa de suscripción mensual a Workspace, por lo que no hay facturación directa por el uso de las APIs de Gmail, Google Drive, Calendario, Documentos, Hojas de cálculo y Presentaciones.
Los diferentes productos de Google se facturan de manera diferente, así que asegúrate de consultar la documentación de tu API para obtener esa información.
Resumen
Ahora que ya sabes cómo habilitar las APIs de Google en general, ve al Administrador de API y habilita la API de Cloud Translation y el servicio de App Engine (si aún no lo has hecho). La primera opción porque la usará nuestra aplicación y la segunda porque implementarás una app de App Engine. Si prefieres hacerlo desde la línea de comandos, ejecuta este comando en su lugar:
gcloud services enable appengine.googleapis.com translate.googleapis.com
Si bien su cuota mensual no aparece en la lista de la lista general "Siempre gratuito" nivel de resumen, la página de precios de la API de Translation indica que todos los usuarios reciben una cantidad fija de caracteres traducidos por mes. No se te debería cobrar ningún cargo a la API si te mantienes por debajo de ese umbral. Si hay otros cargos relacionados con Google Cloud, se analizarán al final de la sección “Limpieza” sección.
4. Obtén el código de la app de ejemplo
Clona el código del repositorio de forma local o en Cloud Shell (con el comando git clone
), o descarga el archivo ZIP del botón verde Code, como se muestra en la siguiente captura de pantalla:
Ahora que tienes todo, crea una copia completa de la carpeta para hacer este instructivo específico, ya que es probable que implique borrar o cambiar los archivos. Si quieres realizar una implementación diferente, puedes comenzar de nuevo copiando la original para no tener que clonarla ni descargarla de nuevo.
5. Recorrido por la app de ejemplo
La app de ejemplo es un derivado sencillo de Google Traductor que les indica a los usuarios que ingresen un texto en inglés y reciban la traducción equivalente de ese texto en español. Ahora, abre el archivo main.py
para que podamos ver cómo funciona. Si omites las líneas comentadas sobre las licencias, se verá de la siguiente manera en la parte inferior y superior:
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)))
- Las importaciones aportan la funcionalidad de Flask, el módulo
google.auth
y la biblioteca cliente de la API de Cloud Translation. - Las variables globales representan la app de Flask, el ID del proyecto de Cloud, el cliente de la API de Translation y la “ruta de ubicación” superior. para las llamadas a la API de Translation, así como los idiomas fuente y objetivo. En este caso, es inglés (
en
) y español (es
), pero puedes cambiar estos valores a otros códigos de idioma compatibles con la API de Cloud Translation. - El bloque
if
grande que aparece en la parte inferior se usa en el instructivo para ejecutar esta app de manera local; usa el servidor de desarrollo Flask para entregar la app. Esta sección también está disponible para los instructivos de implementación de Cloud Run en caso de que el servidor web no esté empaquetado en el contenedor. Se te solicita que habilites la agrupación del servidor en el contenedor, pero, en caso de que no la tengas en cuenta, el código de la app recurre al uso del servidor de desarrollo de Flask. No es un problema de App Engine ni de Cloud Functions porque son plataformas basadas en fuentes, lo que significa que Google Cloud proporciona y ejecuta un servidor web predeterminado.
Por último, en medio de main.py
está el corazón de la aplicación, la función 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)
La función principal toma la entrada del usuario y llama a la API de Translation para realizar el trabajo pesado. Analicemos esto:
- Usa la variable
local_request
para verificar si las solicitudes provienen de Cloud Functions. Cloud Functions envía su propio objeto Flask Request, mientras que todos los demás (que se ejecutan de forma local o se implementan en App Engine o Cloud Run) obtendrán el objeto de solicitud directamente desde Flask. - Restablece las variables básicas del formulario. Esto es principalmente para solicitudes GET, ya que las solicitudes POST tendrán datos que las reemplazarán.
- Si se trata de un POST, toma el texto que quieras traducir y crea una estructura JSON que represente el requisito de metadatos de la API. Luego, llama a la API y recurre a una versión anterior de la API si el usuario emplea una biblioteca antigua.
- En cualquier caso, formatea los resultados reales (POST) o ningún dato (GET) en el contexto y la renderización de la plantilla.
La parte visual de la aplicación se encuentra en el archivo de plantilla index.html
. Muestra los resultados traducidos anteriormente (en blanco en caso contrario) seguidos del formulario en el que se solicita alguna traducción:
<!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. Cómo instalar paquetes o dependencias locales (en lib)
Como se mencionó anteriormente, la app de ejemplo usa el framework web micro Flask y la biblioteca cliente de la API de Google Cloud Translation para Python. Instala y actualiza pip
además de este par de paquetes con este comando pip
(o pip3
):
pip install -t lib -r requirements.txt
Después de ejecutar el comentario anterior, verás el resultado de la instalación, que puede ser similar al siguiente:
$ 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. Implemente el servicio
Para implementar tu servicio de traducción en Python 2 App Engine, ejecuta este comando:
gcloud app deploy
El resultado debería ser el siguiente y proporcionar algunas indicaciones para los próximos pasos:
$ 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
Ahora que tu app está disponible en todo el mundo, deberías poder acceder a ella en la URL (que contiene el ID del proyecto) proporcionada en el resultado de tu implementación:
Traduce contenido para que funcione.
8. Conclusión
¡Felicitaciones! Aprendiste a habilitar la API de Cloud Translation, obtener las credenciales necesarias e implementar una aplicación web sencilla en Python 2 de App Engine. Puedes obtener más información sobre esta implementación en esta tabla del repositorio.
Limpia
La API de Cloud Translation te permite realizar una cantidad fija de caracteres traducidos por mes de forma gratuita. App Engine también tiene una cuota gratuita, al igual que Cloud Functions y Cloud Run. Se generarán cargos si se excede alguno de esos requisitos. Si planeas continuar con el siguiente codelab, no es necesario que cierres la app.
Sin embargo, si aún no estás listo para ir al siguiente instructivo o te preocupa que Internet descubra la app que acabas de implementar, inhabilita tu app de App Engine, borra tu Cloud Function o inhabilita tu servicio de Cloud Run para evitar que se generen cargos. Cuando estés listo para pasar al siguiente codelab, puedes volver a habilitarla. Por otro lado, si no vas a continuar con esta aplicación o algún otro codelab, y deseas borrar todo por completo, puedes cerrar tu proyecto.
Además, la implementación en una plataforma de procesamiento sin servidores de Google Cloud genera costos menores de compilación y almacenamiento. Cloud Build tiene su propia cuota gratuita, al igual que Cloud Storage. Para una mayor transparencia, Cloud Build compila la imagen de tu aplicación, que luego se almacena en Cloud Container Registry o Artifact Registry, su sucesora. El almacenamiento de esa imagen consume parte de esa cuota, al igual que la salida de red cuando se transfiere esa imagen al servicio. Sin embargo, es posible que vivas en una región que no cuenta con ese nivel gratuito, así que ten en cuenta el uso que haces del almacenamiento para minimizar posibles costos.
9. Recursos adicionales
En las siguientes secciones, encontrarás material de lectura adicional y ejercicios recomendados para aumentar tu conocimiento adquirido tras completar este tutorial.
Estudio adicional
Ahora que ya tienes experiencia con la API de Translation, realicemos algunos ejercicios adicionales para desarrollar aún más tus habilidades. Para continuar tu ruta de aprendizaje, modifica nuestra app de ejemplo para que realice lo siguiente:
- Completa todas las demás ediciones de este codelab para ejecutar de forma local o implementar en plataformas de computación sin servidores de Google Cloud (consulta README del repositorio).
- Completa este instructivo con otro lenguaje de programación.
- Cambia esta aplicación para que sea compatible con diferentes idiomas de origen u objetivo.
- Actualiza esta aplicación para poder traducir texto a más de un idioma. Cambia el archivo de plantilla para que se muestre un menú desplegable con los idiomas de destino admitidos.
Más información
Google App Engine
- Página principal de App Engine
- Documentación de App Engine
- Guía de inicio rápido de App Engine para Python 3
- Cuentas de servicio predeterminadas para App Engine
- Entorno de ejecución de App Engine (estándar) para Python 2
- Entorno de ejecución de App Engine (estándar) para Python 3
- Diferencias entre Python 2 y 3 entornos de ejecución de App Engine (estándar)
- Guía de migración de Python 2 a 3 de App Engine (estándar)
Google Cloud Functions
- Página principal de Cloud Functions
- Documentación de Cloud Functions
- Guía de inicio rápido de Cloud Functions para Python
- Cuentas de servicio predeterminadas para Cloud Functions
Google Cloud Run
- Página principal de Cloud Run
- Documentación de Cloud Run
- Guía de inicio rápido de Cloud Run para Python
- Cuentas de servicio predeterminadas para Cloud Run
Google Cloud Buildpacks, Container Registry y Artifact Registry
- Anuncio de Cloud Buildpacks
- Repositorio de Cloud Buildpacks
- Página principal de Cloud Artifact Registry
- Documentación de Cloud Artifact Registry
- Página principal de Cloud Container Registry
- Documentación de Cloud Container Registry
Google Cloud Translation y el kit de AA de Google
- Página principal de Cloud Translation
- Documentación de Cloud Translation
- Página de precios de la API de Translation
- Todos los “componentes básicos” de la IA y el AA de Cloud APIs
- Kit de AA de Google (subconjunto de APIs de Cloud AI/AA para dispositivos móviles)
- API de Google ML Kit Translation
Otros productos o páginas de Google Cloud
- Compatibilidad de Google Cloud con Python
- Bibliotecas cliente de Google Cloud
- Google Cloud “Siempre gratuito” nivel
- Toda la documentación de Google Cloud
Python y Flask
Licencia
Este instructivo cuenta con una licencia genérica de Creative Commons Attribution 2.0, mientras que el código fuente del repositorio está sujeto a Apache 2.