1. Introducción
Python es un lenguaje de programación de código abierto popular que usan científicos de datos, desarrolladores de aplicaciones web, administradores de sistemas y mucho más.
Cloud Functions es una plataforma de procesamiento sin servidores controlada por eventos. Con Cloud Functions, puedes escribir tu código sin preocuparte por aprovisionar recursos ni escalar para manejar los requisitos cambiantes.
Existen dos tipos de funciones de Cloud Functions:
- Las funciones de HTTP responden a las solicitudes HTTP. Crearás un par en este codelab.
- Las funciones en segundo plano se activan mediante eventos, como la publicación de un mensaje en Cloud Pub/Sub o la carga de un archivo a Cloud Storage. Este tema no se aborda en este lab, pero puedes leer más en la documentación.
En este codelab, te ayudaremos a crear tus propias funciones de Cloud Functions en Python.
Qué compilarás
En este codelab, publicarás una Cloud Function que, cuando se invoca a través de HTTP, muestra el estado "Python Powered" Logotipo:
Qué aprenderás
- Cómo escribir una Cloud Function de HTTP
- Cómo escribir una Cloud Function de HTTP que tome argumentos
- Cómo probar una Cloud Function de HTTP
- Cómo ejecutar un servidor HTTP local de Python para probar la función
- Cómo escribir una Cloud Function de HTTP que muestre una imagen
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 cadena de caracteres que no se utiliza en las APIs de Google. Puedes actualizarla cuando quieras.
- El ID del proyecto es único en todos los proyectos de Google Cloud y es inmutable (no se puede cambiar después de configurarlo). La consola de Cloud genera automáticamente una cadena única. Por lo general, no importa cuál sea. En la mayoría de los codelabs, deberás hacer referencia al ID de tu proyecto (suele identificarse como
PROJECT_ID
). Si no te gusta el ID que se generó, podrías generar otro aleatorio. También puedes probar uno propio y ver si está disponible. No se puede cambiar después de este paso y se usa el mismo durante todo el proyecto. - Recuerda que hay un tercer valor, un número de proyecto, que usan algunas APIs. Obtén más información sobre estos tres valores en la documentación.
- A continuación, deberás habilitar la facturación en la consola de Cloud para usar las APIs o los recursos de Cloud. Ejecutar este codelab no costará mucho, tal vez nada. Para cerrar recursos y evitar que se generen cobros más allá de este instructivo, puedes borrar los recursos que creaste o borrar el proyecto. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de $300.
Inicie Cloud Shell
Si bien Google Cloud se puede operar de manera remota desde tu laptop, en este codelab usarás Cloud Shell, un entorno de línea de comandos que se ejecuta en la nube.
Activar Cloud Shell
- En la consola de Cloud, haz clic en Activar Cloud Shell.
Si es la primera vez que inicias Cloud Shell, verás una pantalla intermedia que describe en qué consiste. Si apareció una pantalla intermedia, haz clic en Continuar.
El aprovisionamiento y la conexión a Cloud Shell solo tomará unos minutos.
Esta máquina virtual está cargada con todas las herramientas de desarrollo necesarias. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que mejora considerablemente el rendimiento de la red y la autenticación. Gran parte de tu trabajo en este codelab, si no todo, se puede hacer con un navegador.
Una vez que te conectes a Cloud Shell, deberías ver que estás autenticado y que el proyecto está configurado con tu ID del proyecto.
- En Cloud Shell, ejecuta el siguiente comando para confirmar que tienes la autenticación:
gcloud auth list
Resultado del comando
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- Ejecuta el siguiente comando en Cloud Shell para confirmar que el comando de gcloud conoce tu proyecto:
gcloud config list project
Resultado del comando
[core] project = <PROJECT_ID>
De lo contrario, puedes configurarlo con el siguiente comando:
gcloud config set project <PROJECT_ID>
Resultado del comando
Updated property [core/project].
Asegúrate de que las APIs de Cloud Functions y Cloud Build estén habilitadas
Ejecuta el siguiente comando desde Cloud Shell para asegurarte de que las APIs de Cloud Functions y Cloud Build estén habilitadas:
gcloud services enable \ cloudfunctions.googleapis.com \ cloudbuild.googleapis.com
Nota: El comando gcloud functions deploy
llamará a Cloud Build, que compilará automáticamente tu código en una imagen de contenedor.
Descargue el código fuente
En la terminal de Cloud Shell, ejecuta los siguientes comandos:
REPO_NAME="codelabs" REPO_URL="https://github.com/GoogleCloudPlatform/$REPO_NAME" SOURCE_DIR="cloud-functions-python-http" git clone --no-checkout --filter=blob:none --depth=1 $REPO_URL cd $REPO_NAME git sparse-checkout set $SOURCE_DIR git checkout cd $SOURCE_DIR
Revisa el contenido del directorio del código fuente:
ls
Deberías tener los siguientes archivos:
main.py python-powered.png test_main.py web_app.py
3. Introducción a Cloud Functions de HTTP
Las funciones de HTTP de Cloud Functions en Python se escriben como funciones normales de Python. La función debe aceptar un solo argumento flask.Request
, que suele llamarse request
.
main.py
import flask
def hello_world(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- "Hello World! 👋"
"""
response = "Hello World! 👋"
return flask.Response(response, mimetype="text/plain")
# ...
Puedes abrir el archivo con tu editor de línea de comandos preferido (nano, vim o emacs). También puedes abrirlo en el Editor de Cloud Shell después de configurar el directorio del código fuente como lugar de trabajo:
cloudshell open-workspace .
Implementaremos esta función como una Cloud Function de HTTP con el comando gcloud functions deploy
:
FUNCTION_NAME="hello_world" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Resultado del comando:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
Notas sobre las opciones de gcloud functions deploy
:
--runtime
: Especifica el entorno de ejecución del lenguaje. Para Python, actualmente puede serpython37
,python38
,python39
,python310
opython312
. Consulta Tiempos de ejecución.--trigger-http
: Se asignará un extremo a la función. Las solicitudes HTTP (POST, PUT, GET, DELETE y OPTIONS) al extremo activarán la ejecución de la función.--allow-unauthenticated
: La función será pública, lo que permitirá todos los emisores, sin verificar la autenticación.- Para obtener más información, consulta gcloud functions deploy.
Para probar la función, puedes hacer clic en la URL httpsTrigger.url
que se muestra en el resultado del comando anterior. También puedes recuperar la URL de manera programática y llamar a la función con los siguientes comandos:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
Deberías obtener el siguiente resultado:
Hello World! 👋
4. Escribe una Cloud Function de HTTP que tome argumentos
Las funciones son más versátiles cuando aceptan argumentos. Definamos una nueva función hello_name
que admita un parámetro name
:
main.py
# ...
def hello_name(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- "Hello {NAME}! 🚀" if "name=NAME" is defined in the GET request
- "Hello World! 🚀" otherwise
"""
name = request.args.get("name", "World")
response = f"Hello {name}! 🚀"
return flask.Response(response, mimetype="text/plain")
# ...
Implementemos esta nueva función:
FUNCTION_NAME="hello_name" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Resultado del comando:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
Para probar la función, puedes hacer clic en la URL httpsTrigger.url
que se muestra en el resultado del comando anterior. También puedes recuperar la URL de manera programática y llamar a la función con los siguientes comandos:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
Deberías obtener el resultado predeterminado:
Hello World! 🚀
Obtendrás el resultado predeterminado porque no se estableció el argumento name
. Agrega un parámetro a la URL:
curl -w "\n" $URL?name=YOUR%20NAME
Esta vez, obtendrás tu respuesta personalizada:
Hello YOUR NAME! 🚀
El siguiente paso es agregar pruebas de unidades para garantizar que las funciones sigan funcionando según lo previsto cuando se actualice el código fuente.
5. Escribir pruebas
Las funciones de HTTP de Cloud Functions en Python se prueban con el módulo unittest
de la biblioteca estándar. No es necesario que ejecutes un emulador ni otra simulación para probar tu función; solo es código normal de Python.
Así se ve una prueba para las funciones hello_world
y hello_name
:
test_main.py
import unittest
import unittest.mock
import main
class TestHello(unittest.TestCase):
def test_hello_world(self):
request = unittest.mock.Mock()
response = main.hello_world(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == "Hello World! 👋"
def test_hello_name_no_name(self):
request = unittest.mock.Mock(args={})
response = main.hello_name(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == "Hello World! 🚀"
def test_hello_name_with_name(self):
name = "FirstName LastName"
request = unittest.mock.Mock(args={"name": name})
response = main.hello_name(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == f"Hello {name}! 🚀"
- Las pruebas de Python se escriben de la misma manera que otros archivos de Python. Empieza con un conjunto de importaciones y, luego, define clases y funciones.
- La declaración de prueba tiene el formato
class TestHello(TestCase)
. Debe ser una clase que se herede deunittest.TestCase
. - La clase de prueba tiene métodos, cada uno de los cuales debe comenzar con
test_
, que representan casos de prueba individuales. - Cada caso de prueba prueba una de nuestras funciones simulando el parámetro
request
(es decir, reemplazándolo por un objeto falso con los datos específicos requeridos para la prueba). - Después de invocar cada función, la prueba verifica la respuesta HTTP para asegurarse de que sea lo que esperábamos.
Como main.py
depende de flask
, asegúrate de que el framework de Flask esté instalado en tu entorno de pruebas:
pip install flask
La instalación de Flask genera un resultado similar al siguiente:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
Ejecuta estas pruebas de manera local:
python -m unittest
Las tres pruebas de unidades deben aprobarse:
... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK
A continuación, crearás una nueva función que devuelva el comando “Python Powered” logotipo.
6. Escribir el curso “Python Powered” Cloud Function de HTTP
Hagamos que una nueva función sea un poco más entretenida devolviendo el código “Python Powered” imagen para cada solicitud:
En la siguiente lista, se muestra el código necesario para realizar esta acción:
main.py
# ...
def python_powered(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- The official "Python Powered" logo
"""
return flask.send_file("python-powered.png")
Implementa una nueva función python_powered
:
FUNCTION_NAME="python_powered" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Resultado del comando:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
Para probar la función, haz clic en la URL httpsTrigger.url
que se muestra en el resultado del comando anterior. Si todo funciona correctamente, verás el mensaje “Python Powered” en una nueva pestaña del navegador.
A continuación, crearás una app para poder ejecutar y probar tu función de manera local antes de implementarla.
7. Ejecuta la función de manera local
Puedes ejecutar una función HTTP de forma local si creas una app web y llamas a tu función en una ruta. Puedes agregarla en el mismo directorio que tu función. El archivo llamado web_app.py
tiene el siguiente contenido:
web_app.py
import flask
import main
app = flask.Flask(__name__)
@app.get("/")
def index():
return main.python_powered(flask.request)
if __name__ == "__main__":
# Local development only
# Run "python web_app.py" and open http://localhost:8080
app.run(host="localhost", port=8080, debug=True)
- Este archivo crea una aplicación Flask.
- Registra una ruta en la URL base que se controla con una función llamada
index()
. - Luego, la función
index()
llama a nuestra funciónpython_powered
y le pasa la solicitud actual.
Asegúrate de que el framework de Flask esté instalado en tu entorno de desarrollo:
pip install flask
La instalación de Flask genera un resultado similar al siguiente:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
Para ejecutar esta aplicación de manera local, ejecuta el siguiente comando:
python web_app.py
Ahora, usa la vista previa web de Cloud Shell para probar la app web en tu navegador. En Cloud Shell, haz clic en “Vista previa en la Web”. y selecciona "Vista previa en el puerto 8080":
Cloud Shell abre la URL de vista previa en una ventana nueva del navegador, en su servicio de proxy. La vista previa en la Web restringe el acceso a través de HTTPS solo a tu cuenta de usuario. Si todo funciona correctamente, deberías ver el mensaje "Python Powered" ¡logotipo!
8. ¡Felicitaciones!
Implementaste Cloud Functions de HTTP con funciones idiomáticas que controlan solicitudes web con el framework de Flask.
Los precios de Cloud Functions se basan en la frecuencia con la que se invoca tu función, lo que incluye un nivel gratuito para las funciones que no se ejecutan con frecuencia. Una vez que termines de probar tus Cloud Functions, puedes borrarlas con gcloud
:
gcloud functions delete hello_world --quiet gcloud functions delete hello_name --quiet gcloud functions delete python_powered --quiet
También puedes borrar las funciones desde la consola de Google Cloud.
Esperamos que disfrutes el uso de Cloud Functions en Python.