Cómo implementar una aplicación web de Flask escrita en Python en el entorno flexible de App Engine

Resumen

En este codelab, aprenderás a implementar una aplicación web de Flask escrita en Python en el entorno flexible de App Engine. La aplicación de ejemplo permite que el usuario suba una foto del rostro de alguien y descubra qué tan probable es que esa persona esté feliz. La aplicación usa las APIs de Google Cloud para Vision, Storage y Datastore.

Acerca de App Engine

Las aplicaciones de Google App Engine son fáciles de crear, mantener y escalar a medida que cambian tus necesidades de almacenamiento de datos y tráfico. Con App Engine, no tendrás que mantener servidores. Solo debes subir tu aplicación y estará lista para usar.

Las aplicaciones de App Engine se escalan automáticamente según el tráfico entrante. El balanceo de cargas, los microservicios, la autorización, las bases de datos SQL y NoSQL, la división del tráfico, el registro, la búsqueda, el control de versiones, el lanzamiento, la reversión y el análisis de seguridad son compatibles de forma nativa y sumamente personalizables.

El entorno flexible de App Engine admite todos los siguientes lenguajes de programación: C#, Go, Java, Node.js, PHP, Python y Ruby. App Engine flexible ejecuta tu aplicación dentro de contenedores de Docker que se ejecutan en máquinas virtuales de Google Compute Engine. El entorno estándar de App Engine es una opción alternativa para ciertos lenguajes, incluido Python. App Engine estándar ejecuta tu aplicación en un entorno de zona de pruebas más restrictivo. Lee Elige un entorno de App Engine para obtener más información.

Qué aprenderás

  • Cómo implementar una aplicación web sencilla para el entorno flexible de App Engine
  • Cómo acceder a bibliotecas cliente de Google Cloud para Vision, Storage y Datastore
  • Cómo usar la consola de Google Cloud y el SDK de Google Cloud para administrar diversos recursos de la nube
  • Cómo usar Cloud Shell

Requisitos

  • Conocimientos de Python
  • Conocimientos de editores de texto estándares de Linux, como Vim, Emacs o Nano

Creación de proyectos

Si aún no tienes una Cuenta de Google (Gmail o Google Apps), debes crear una. Accede a Google Cloud Platform Console (console.cloud.google.com) y crea un proyecto nuevo:

Recuerde el ID de proyecto, un nombre único en todos los proyectos de Google Cloud (el nombre anterior ya se encuentra en uso y no lo podrá usar). Más adelante en este codelab, se hará referencia a él como PROJECT_ID.

Facturación

A continuación, deberás habilitar la facturación en la consola de Cloud para usar los recursos de Google Cloud.

Ejecutar este codelab debería costar solo unos pocos dólares, pero su costo podría aumentar si decides usar más recursos o si los dejas en ejecución.

Los usuarios nuevos de Google Cloud Platform son aptos para obtener una prueba gratuita de USD 300.

Si bien Google Cloud se puede operar de manera remota desde tu laptop, en este codelab usaremos Google Cloud Shell, un entorno de línea de comandos que se ejecuta en la nube. Esta máquina virtual basada en Debian está cargada con todas las herramientas de desarrollo que necesitarás (gcloud, Python, virtualenv, pip y muchas más), ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que mejora en gran medida el rendimiento de la red y la autenticación. Esto significa que todo lo que necesitarás para este Codelab es un navegador (sí, funciona en una Chromebook).

Para activar Google Cloud Shell, haz clic en el botón que se encuentra en la parte superior derecha de la consola para desarrolladores (el aprovisionamiento y la conexión al entorno debería llevar solo unos minutos):

Una vez que te conectes a Cloud Shell, deberías ver que ya te autenticaste y que el proyecto ya se configuró con tu PROJECT_ID:

gcloud auth list
Credentialed accounts:
- <myaccount>@<mydomain>.com (active)
gcloud config list project
[core]
Project = <PROJECT_ID>

Si, por algún motivo, el proyecto no se configuró, solo emite el siguiente comando:

gcloud config set project <PROJECT_ID>

¿No encuentras tu PROJECT_ID? Observa el ID del proyecto que usaste en los pasos de configuración o búscalo en el panel de la consola:

En la línea de comandos de Cloud Shell, ejecute el siguiente comando para clonar el repositorio de GitHub:

git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

Cambie al directorio python-docs-samples/codelabs/flex_and_vision:

cd python-docs-samples/codelabs/flex_and_vision

Antes de comenzar a usar las APIs de Vision, Storage y Datastore, debes habilitarlas con los siguientes comandos:

gcloud services enable vision.googleapis.com
gcloud services enable storage-component.googleapis.com
gcloud services enable datastore.googleapis.com

Para hacer solicitudes a las APIs de Vision, Storage y Datastore, necesitarás credenciales de cuentas de servicio. Las credenciales de la cuenta de servicio de tu proyecto se pueden generar con la herramienta gcloud.

Configura una variable de entorno para tu PROJECT_ID y reemplaza [YOUR_PROJECT_ID] por tu propio ID del proyecto:

export PROJECT_ID=[YOUR_PROJECT_ID]

Crea una cuenta de servicio para acceder a las APIs de Google Cloud cuando realices pruebas locales:

gcloud iam service-accounts create codelab \
  --display-name "My Codelab Service Account"

Otorga los permisos adecuados a tu nueva cuenta de servicio:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:codelab@${PROJECT_ID}.iam.gserviceaccount.com \
--role roles/owner

Después de crear tu cuenta de servicio, crea una clave para ella:

gcloud iam service-accounts keys create ~/key.json \
--iam-account codelab@${PROJECT_ID}.iam.gserviceaccount.com

Este comando genera una clave de cuenta de servicio que se almacena en un archivo JSON llamado key.json en tu directorio principal.

Usa la ruta de acceso absoluta de la clave generada para establecer una variable de entorno para tu clave de cuenta de servicio en Cloud Shell:

export GOOGLE_APPLICATION_CREDENTIALS="/home/${USER}/key.json"

Obtén más información para autenticar la API de Vision.

Cómo iniciar tu entorno virtual e instalar dependencias

Crea un entorno aislado de Python 3 llamado env con virtualenv:

virtualenv -p python3 env

Ingresa tu nuevo entorno virtualenv llamado env:

source env/bin/activate

Usa pippara instalar las dependencias de tu proyecto desde el archivo requirements.txt:

pip install -r requirements.txt

El archivo requirements.txt es una lista de las dependencias de paquetes que necesitas para tu proyecto. El comando anterior descargó todas estas dependencias de paquetes en virtualenv.

Cómo crear una aplicación de App Engine

A continuación, crea una instancia de App Engine usando lo siguiente:

gcloud app create

Cómo crear un depósito de Storage

Primero, define la variable de entorno CLOUD_STORAGE_BUCKET para que sea igual al nombre de tu PROJECT_ID. Generalmente, se recomienda que asigne a su depósito el mismo nombre que para PROJECT_ID por conveniencia.

export CLOUD_STORAGE_BUCKET=${PROJECT_ID}

Nuestra aplicación usa un bucket de Cloud Storage, que deberás crear desde Cloud Shell con una herramienta llamada gsutil. Ejecuta el siguiente comando, que crea un bucket con el mismo nombre que tu PROJECT_ID.

gsutil mb gs://${PROJECT_ID}

Ejecute la aplicación

python main.py

Una vez que se inicie la aplicación, haz clic en el ícono de Vista previa en la Web , en la barra de herramientas de Cloud Shell, y selecciona "Vista previa en el puerto 8080".

En tu navegador, se abrirá una pestaña y se conectará al servidor que acabas de iniciar. Debería ver algo como esto:

Screen Shot 2017-02-23 at 7.22.50 PM.png

Intenta subir una foto que contenga un rostro humano. Haz clic en el botón Elegir archivo, elige una imagen de tu computadora y, luego, haz clic en Enviar.

Después de subir una foto, deberías ver algo como esto:

Screen Shot 2017-02-23 at 7.32.08 PM.png

Diseño de muestra del código

La muestra tiene el siguiente diseño:

templates/
  homepage.html   /* HTML template that uses Jinja2 */
app.yaml          /* App Engine application configuration file */
main.py           /* Python Flask web application */
requirements.txt  /* List of dependencies for the project */

main.py

Este archivo de Python es una aplicación web de Flask. La aplicación permite que los usuarios envíen fotos (preferentemente de rostros), las cuales se almacenan en Cloud Storage y se analizan con la función de detección de rostro de la API de Cloud Vision. La información clave sobre cada foto se almacena en Datastore, la base de datos NoSQL de Google Cloud Platform, a la que se accede cada vez que un usuario visita el sitio web.

Esta aplicación usa las bibliotecas cliente de Google Cloud Platform para Storage, Datastore y Vision. Estas bibliotecas cliente facilitan el acceso a las API de Cloud desde sus lenguajes de programación preferidos.

Veamos algunos fragmentos clave del código.

En la sección de importaciones, ubicada en la parte superior, importamos los distintos paquetes que necesitamos para nuestro código. Importamos las bibliotecas cliente de Google Cloud para Datastore, Storage y Vision de esta manera:

from google.cloud import datastore
from google.cloud import storage
from google.cloud import vision

Este código muestra lo que sucede cuando un usuario visita la URL raíz del sitio web. Creamos un objeto cliente de Datastore, que se usa para acceder a la biblioteca cliente de Datastore. Luego, ejecutamos una consulta en Datastore para entidades del tipo Rostros. Por último, renderizamos nuestra plantilla HTML y pasamos image_entities, que extrajimos de Datastore como una variable.

@app.route('/')
def homepage():
    # Create a Cloud Datastore client.
    datastore_client = datastore.Client()

    # Use the Cloud Datastore client to fetch information from Datastore about
    # each photo.
    query = datastore_client.query(kind='Faces')
    image_entities = list(query.fetch())

    # Return a Jinja2 HTML template and pass in image_entities as a parameter.
    return render_template('homepage.html', image_entities=image_entities)

Analicemos cómo se guardan las entidades en Datastore. Datastore es la solución de base de datos NoSQL de Google Cloud. Los datos se almacenan en objetos llamados entidades. A cada entidad se le asigna una clave única de identificación, que se puede crear usando un tipo y una cadena de nombre de clave. Un tipo es un depósito de organización que designa el tipo de entidad que es. Por ejemplo, es posible que desee configurar tipos para fotos, personas y animales.

Cada entidad puede tener muchas propiedades definidas por el desarrollador, las cuales pueden tener valores de varios tipos, incluidos números enteros, flotantes, strings, fechas o datos binarios.

    # Create a Cloud Datastore client.
    datastore_client = datastore.Client()

    # Fetch the current date / time.
    current_datetime = datetime.now()

    # The kind for the new entity.
    kind = 'Faces'

    # The name/ID for the new entity.
    name = blob.name

    # Create the Cloud Datastore key for the new entity.
    key = datastore_client.key(kind, name)

    # Construct the new entity using the key. Set dictionary values for entity
    # keys blob_name, storage_public_url, timestamp, and joy.
    entity = datastore.Entity(key)
    entity['blob_name'] = blob.name
    entity['image_public_url'] = blob.public_url
    entity['timestamp'] = current_datetime
    entity['joy'] = face_joy

    # Save the new entity to Datastore.
    datastore_client.put(entity)

De manera similar a Datastore, se puede acceder a las bibliotecas cliente de Storage y Vision de forma programática. Puedes abrir el archivo main.py tú mismo con vim, emacs o nano para explorar todo el código de muestra.

Obtén más información sobre Flask en http://flask.pocoo.org/.

Obtén más información sobre las bibliotecas cliente en https://googlecloudplatform.github.io/google-cloud-python/.

homepage.html

El framework web de Flask aprovecha Jinja2 como un motor de plantillas. Esto nos permite pasar variables y expresiones de main.py a homepage.html que se reemplazan por valores cuando la página se procesa.

Obtenga más información sobre Jinja2 en http://jinja.pocoo.org/docs/2.9/templates/.

Esta plantilla HTML de Jinja2 muestra un formulario para que los usuarios envíen fotos a la base de datos. También muestra cada imagen que se envió antes junto con su nombre de archivo, hora y fecha de carga, y la probabilidad de que el rostro detectado por la API de Vision esté feliz.

homepage.html

<h1>Google Cloud Platform - Face Detection Sample</h1>

<p>This Python Flask application demonstrates App Engine Flexible, Google Cloud
Storage, Datastore, and the Cloud Vision API.</p>

<br>

<html>
  <body>
    <form action="upload_photo" method="POST" enctype="multipart/form-data">
      Upload File: <input type="file" name="file"><br>
      <input type="submit" name="submit" value="Submit">
    </form>
    
  </body>
</html>

El entorno flexible de App Engine utiliza un archivo llamado app.yaml para describir la configuración de implementación de una aplicación. Si falta ese archivo, App Engine intentará deducir la configuración de la implementación. Sin embargo, se recomienda proporcionar este archivo.

A continuación, modificarás app.yaml con el editor que prefieras: vim, nano o emacs. Usaremos el editor nano:

nano app.yaml

app.yaml

runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app

runtime_config:
    python_version: 3

env_variables:
    CLOUD_STORAGE_BUCKET: <your-cloud-storage-bucket>

Esta es la configuración básica que se necesita para implementar una aplicación de Python 3 en el entorno flexible de App Engine. Puedes obtener más información para configurar App Engine aquí.

Cuando app.yaml esté abierto, reemplaza < your-cloud-storage-bucket > por el nombre de tu bucket de Cloud Storage. (Si olvidaste el nombre de tu bucket de Cloud Storage, copia el ID del proyecto de GCP de Qwiklabs, que es el mismo). La sección env_variables define las variables de entorno que se usarán en main.py cuando se implemente la aplicación.

Ahora puede guardar y cerrar el archivo en nano con (Ctrl + x), que mostrará lo siguiente:

Screen Shot 2017-02-17 at 4.47.12 PM.png

Escribe una letra y y, luego, presiona la tecla INTRO una vez más para confirmar el nombre del archivo cuando aparezca el siguiente mensaje:

Screen Shot 2017-02-24 at 4.18.23 PM.png

Usa gcloud para implementar tu aplicación en App Engine:

gcloud app deploy

Después de implementar la aplicación, podrás acceder a ella si abres la URL https://< PROJECT_ID >.appspot.com en tu navegador web.

Resumen

En este paso, configuraste una aplicación web de Python y la implementaste en el entorno flexible de App Engine.

Aprendiste a escribir y a desplegar tu primera aplicación web flexible de App Engine.

Limpieza

Sigue estos pasos para evitar que se apliquen cargos a tu cuenta de Google Cloud Platform por los recursos de esta guía de inicio rápido:

  • Ve a Cloud Platform Console.
  • Selecciona el proyecto que deseas cerrar y, luego, haz clic en “Borrar” en la parte superior para programar su eliminación.

Más información

Licencia

Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.