Guía de Azure Functions para desarrolladores de PythonAzure Functions Python developer guide

Este artículo es una introducción al desarrollo de Azure Functions mediante Python.This article is an introduction to developing Azure Functions using Python. En lo que va a leer a continuación se supone que ya ha leído la guía para desarrolladores de Azure Functions.The content below assumes that you've already read the Azure Functions developers guide.

Nota

Python para Azure Functions actualmente se encuentra disponible en versión preliminar.Python for Azure Functions is currently in preview. Para recibir actualizaciones importantes, suscríbase al repositorio de anuncios de Azure App Service en GitHub.To receive important updates, subscribe to the Azure App Service announcements repository on GitHub.

Modelo de programaciónProgramming model

Una función de Azure Function debe ser un método sin estado de un script de Python que procese entradas y produzca salidas.An Azure Function should be a stateless method in your Python script that processes input and produces output. De forma predeterminada, el tiempo de ejecución espera que el método se implementa como un método global denominado main() en el __init__.py archivo.By default, the runtime expects the method to be implemented as a global method called main() in the __init__.py file.

Puede cambiar la configuración predeterminada si especifica las propiedades scriptFile y entryPoint en el archivo function.json.You can change the default configuration by specifying the scriptFile and entryPoint properties in the function.json file. Por ejemplo, el archivo function.json siguiente indica al entorno de ejecución que use el método customentry() del archivo main.py, como punto de entrada para la función de Azure.For example, the function.json below tells the runtime to use the customentry() method in the main.py file, as the entry point for your Azure Function.

{
  "scriptFile": "main.py",
  "entryPoint": "customentry",
  ...
}

Los datos de los desencadenadores y enlaces se enlazan a la función a través de los atributos del método con la propiedad name definida en el archivo de configuración function.json.Data from triggers and bindings is bound to the function via method attributes using the name property defined in the function.json configuration file. Por ejemplo, el function.json a continuación se describe una función simple desencadenada por una solicitud HTTP denominada req:For example, the function.json below describes a simple function triggered by an HTTP request named req:

{
  "bindings": [
    {
      "name": "req",
      "direction": "in",
      "type": "httpTrigger",
      "authLevel": "anonymous"
    },
    {
      "name": "$return",
      "direction": "out",
      "type": "http"
    }
  ]
}

El archivo __init__.py contiene el código de función siguiente:The __init__.py file contains the following function code:

def main(req):
    user = req.params.get('user')
    return f'Hello, {user}!'

Si lo desea, también puede declarar los tipos de parámetros y el tipo de valor devuelto de la función mediante las anotaciones de tipos de Python.Optionally, you can also declare the parameter types and return type in the function using Python type annotations. Por ejemplo, puede escribir la misma función con anotaciones, como sigue:For example, the same function can be written using annotations, as follows:

import azure.functions

def main(req: azure.functions.HttpRequest) -> str:
    user = req.params.get('user')
    return f'Hello, {user}!'

Utilice las anotaciones de Python incluidas en el paquete azure.functions.* para enlazar las entradas y las salidas a los métodos.Use the Python annotations included in the azure.functions.* package to bind input and outputs to your methods.

Estructura de carpetasFolder structure

La estructura de carpetas para un proyecto de Python de Azure Functions tiene la siguiente apariencia:The folder structure for a Python Functions project looks like the following:

 FunctionApp
 | - MyFirstFunction
 | | - __init__.py
 | | - function.json
 | - MySecondFunction
 | | - __init__.py
 | | - function.json
 | - SharedCode
 | | - myFirstHelperFunction.py
 | | - mySecondHelperFunction.py
 | - host.json
 | - requirements.txt
 | - extensions.csproj
 | - bin

Hay un archivo host.json compartido que se puede usar para configurar la aplicación de función.There's a shared host.json file that can be used to configure the function app. Cada función tiene su propio archivo de código y archivo de configuración de enlace (function.json).Each function has its own code file and binding configuration file (function.json).

El código compartido debe mantenerse en una carpeta independiente.Shared code should be kept in a separate folder. Para hacer referencia a los módulos en la carpeta SharedCode, puede usar la sintaxis siguiente:To reference modules in the SharedCode folder, you can use the following syntax:

from ..SharedCode import myFirstHelperFunction

Las extensiones de enlace que usa el entorno de ejecución de Functions se definen en el archivo extensions.csproj, mientras que los archivos de biblioteca reales se hallan en la carpeta bin.Binding extensions used by the Functions runtime are defined in the extensions.csproj file, with the actual library files in the bin folder. Al desarrollar de forma local, debe registrar las extensiones de enlace con Azure Functions Core Tools.When developing locally, you must register binding extensions using Azure Functions Core Tools.

Al implementar un proyecto de Functions en la aplicación de función en Azure, todo el contenido de la carpeta FunctionApp debe incluirse en el paquete, pero no en la carpeta.When deploying a Functions project to your function app in Azure, the entire content of the FunctionApp folder should be included in the package, but not the folder itself.

Los desencadenadores y las entradasTriggers and Inputs

Las entradas se dividen en dos categorías dentro de Azure Functions: una entrada del desencadenador y otra adicional.Inputs are divided into two categories in Azure Functions: trigger input and additional input. Aunque son diferentes en function.json, se usan igual en el código de Python.Although they are different in function.json, the usage is identical in Python code. Las cadenas de conexión para orígenes de entrada y de desencadenador deben asignar a los valores de la local.settings.json archivo localmente y la configuración de la aplicación cuando se ejecuta en Azure.Connection strings for trigger and input sources should map to values in the local.settings.json file locally, and the application settings when running in Azure. Tomemos el siguiente fragmento de código a modo de ejemplo:Let's take the following code snippet as an example:

// function.json
{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "req",
      "direction": "in",
      "type": "httpTrigger",
      "authLevel": "anonymous",
      "route": "items/{id}"
    },
    {
      "name": "obj",
      "direction": "in",
      "type": "blob",
      "path": "samples/{id}",
      "connection": "AzureWebJobsStorage"
    }
  ]
}
// local.settings.json
{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsStorage": "<azure-storage-connection-string>"
  }
}
# __init__.py
import azure.functions as func
import logging

def main(req: func.HttpRequest,
         obj: func.InputStream):

    logging.info(f'Python HTTP triggered function processed: {obj.read()}')

Cuando se invoca la función, la solicitud HTTP se pasa a la función como req.When the function is invoked, the HTTP request is passed to the function as req. Una entrada se recuperan desde el almacenamiento de blobs de Azure según la ID en la dirección URL de ruta y ponen a disposición como obj en el cuerpo de la función.An entry will be retrieved from the Azure Blob Storage based on the ID in the route URL and made available as obj in the function body. Aquí, la cuenta de almacenamiento especificado se encuentra la cadena de conexión en AzureWebJobsStorage que es la misma cuenta de almacenamiento utilizada por la aplicación de función.Here the storage account specified is the connection string found in AzureWebJobsStorage which is the same storage account used by the function app.

SalidasOutputs

Las salidas se pueden expresar como valores devueltos y como parámetros de salida.Output can be expressed both in return value and output parameters. Si hay una única salida, se recomienda usar el valor devuelto.If there's only one output, we recommend using the return value. Para varias salidas, deberá utilizar parámetros de salida.For multiple outputs, you'll have to use output parameters.

Para usar el valor devuelto de una función como valor de un enlace de salida, la propiedad name del enlace debe establecerse como $return en function.json.To use the return value of a function as the value of an output binding, the name property of the binding should be set to $return in function.json.

Si desea generar varias salidas, utilice el método set() que la interfaz azure.functions.Out ofrece para asignar un valor al enlace.To produce multiple outputs, use the set() method provided by the azure.functions.Out interface to assign a value to the binding. Por ejemplo, la siguiente función puede insertar un mensaje en una cola y también devolver una respuesta HTTP.For example, the following function can push a message to a queue and also return an HTTP response.

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "req",
      "direction": "in",
      "type": "httpTrigger",
      "authLevel": "anonymous"
    },
    {
      "name": "msg",
      "direction": "out",
      "type": "queue",
      "queueName": "outqueue",
      "connection": "AzureWebJobsStorage"
    },
    {
      "name": "$return",
      "direction": "out",
      "type": "http"
    }
  ]
}
import azure.functions as func

def main(req: func.HttpRequest,
         msg: func.Out[func.QueueMessage]) -> str:

    message = req.params.get('body')
    msg.set(message)
    return message

RegistroLogging

El acceso al registrador del entorno de ejecución de Azure Functions está disponible a través de un controlador logging raíz en la aplicación de función.Access to the Azure Functions runtime logger is available via a root logging handler in your function app. Este registrador está asociado a Application Insights y permite marcar las advertencias y los errores detectados durante la ejecución de la función.This logger is tied to Application Insights and allows you to flag warnings and errors encountered during the function execution.

En el ejemplo siguiente se registra un mensaje de información cuando la función se invoca con un desencadenador HTTP.The following example logs an info message when the function is invoked via an HTTP trigger.

import logging

def main(req):
    logging.info('Python HTTP trigger function processed a request.')

Hay métodos de registro adicionales disponibles que permiten escribir en la consola en otros niveles de seguimiento:Additional logging methods are available that let you write to the console at different trace levels:

MétodoMethod DESCRIPCIÓNDescription
logging.critical(message)logging.critical(message) Escribe un mensaje con el nivel CRÍTICO en el registrador de raíz.Writes a message with level CRITICAL on the root logger.
logging.error(message)logging.error(message) Escribe un mensaje con el nivel ERROR en el registrador de raíz.Writes a message with level ERROR on the root logger.
logging.warning(message)logging.warning(message) Escribe un mensaje con el nivel ADVERTENCIA en el registrador de raíz.Writes a message with level WARNING on the root logger.
logging.info(message)logging.info(message) Escribe un mensaje con el nivel INFO en el registrador de raíz.Writes a message with level INFO on the root logger.
logging.debug(message)logging.debug(message) Escribe un mensaje con el nivel DEBUG en el registrador de raíz.Writes a message with level DEBUG on the root logger.

Importación de código compartido en un módulo de funciónImporting shared code into a function module

Los módulos de Python que se publican junto con los módulos de función deben importarse con la sintaxis de importación relativa:Python modules published alongside function modules must be imported using the relative import syntax:

from . import helpers  # Use more dots to navigate up the folder structure.
def main(req: func.HttpRequest):
    helpers.process_http_request(req)

Como alternativa, coloque el código compartido en un paquete independiente, publíquelo en una instancia de PyPI privada o pública, y especifíquelo como una dependencia normal.Alternatively, put shared code into a standalone package, publish it to a public or a private PyPI instance, and specify it as a regular dependency.

AsyncAsync

Puesto que solo puede existir un único proceso de Python por cada aplicación de función, se recomienda implementar la función de Azure como una corrutina asincrónica mediante la instrucción async def.Since only a single Python process can exist per function app, it is recommended to implement your Azure Function as an asynchronous coroutine using the async def statement.

# Will be run with asyncio directly
async def main():
    await some_nonblocking_socket_io_op()

Si la función main() es sincrónica (no tiene el calificador async), se ejecuta automáticamente en un grupo de subprocesos asyncio.If the main() function is synchronous (no async qualifier) we automatically run it in an asyncio thread-pool.

# Would be run in an asyncio thread-pool
def main():
    some_blocking_socket_io()

ContextContext

Para obtener el contexto de invocación de una función durante la ejecución, incluya el argumento context en su firma.To get the invocation context of a function during execution, include the context argument in its signature.

Por ejemplo: For example:

import azure.functions

def main(req: azure.functions.HttpRequest,
            context: azure.functions.Context) -> str:
    return f'{context.invocation_id}'

La clase Context tiene los métodos siguientes:The Context class has the following methods:

function_directory
El directorio en que se ejecuta la función.The directory in which the function is running.

function_name
El nombre de la función.Name of the function.

invocation_id
El identificador de la invocación de la función actual.ID of the current function invocation.

La versión de Python y la administración de paquetes.Python version and package management

Actualmente, Azure Functions admite solo Python 3.6.x (distribución oficial de CPython).Currently, Azure Functions only supports Python 3.6.x (official CPython distribution).

Al desarrollar localmente con Azure Functions Core Tools o Visual Studio Code, agregue los nombres y las versiones de los paquetes necesarios al archivo requirements.txt e instálelos mediante pip.When developing locally using the Azure Functions Core Tools or Visual Studio Code, add the names and versions of the required packages to the requirements.txt file and install them using pip.

Por ejemplo, se puede usar el comando de archivo y pip siguiente para instalar el paquete requests desde PyPI.For example, the following requirements file and pip command can be used to install the requests package from PyPI.

pip install requests
requests==2.19.1
pip install -r requirements.txt

Cuando esté preparado para la publicación, asegúrese de que todas sus dependencias se muestran en el archivo requirements.txt, que se encuentra en la raíz del directorio del proyecto.When you're ready for publishing, make sure that all your dependencies are listed in the requirements.txt file, located at the root of your project directory. Para ejecutar correctamente Azure Functions, el archivo de requisitos debe contener los siguientes paquetes, como mínimo:To successfully execute your Azure Functions, the requirements file should contain a minimum of the following packages:

azure-functions
azure-functions-worker
grpcio==1.14.1
grpcio-tools==1.14.1
protobuf==3.6.1
six==1.11.0

Publicación en AzurePublishing to Azure

Si usa un paquete que requiere un compilador y no admite la instalación de ruedas compatibles con manylinux desde PyPI, se producirá el error siguiente en la publicación en Azure:If you're using a package that requires a compiler and does not support the installation of manylinux-compatible wheels from PyPI, publishing to Azure will fail with the following error:

There was an error restoring dependencies.ERROR: cannot install <package name - version> dependency: binary dependencies without wheels are not supported.  
The terminal process terminated with exit code: 1

Para compilar y configurar los archivos binarios necesarios automáticamente, instale Docker en el equipo local y ejecute el siguiente comando para publicar con Azure Functions Core Tools (func).To automatically build and configure the required binaries, install Docker on your local machine and run the following command to publish using the Azure Functions Core Tools (func). Reemplace <app name> por el nombre de la aplicación de función de Azure.Remember to replace <app name> with the name of your function app in Azure.

func azure functionapp publish <app name> --build-native-deps

Interiormente, Core Tools usará Docker para ejecutar la imagen mcr.microsoft.com/azure-functions/python como un contenedor en la máquina local.Underneath the covers, Core Tools will use docker to run the mcr.microsoft.com/azure-functions/python image as a container on your local machine. Con este entorno, se compilarán e instalarán los módulos necesarios desde la distribución de origen, antes de empaquetarlos para la implementación final en Azure.Using this environment, it'll then build and install the required modules from source distribution, before packaging them up for final deployment to Azure.

Nota

Core Tools (func) usa el programa PyInstaller para inmovilizar el código y las dependencias del usuario en un único ejecutable independiente que se ejecutará en Azure.Core Tools (func) uses the PyInstaller program to freeze the user's code and dependencies into a single stand-alone executable to run in Azure. Esta funcionalidad está actualmente en versión preliminar y no puede extenderse a todos los tipos de paquetes de Python.This functionality is currently in preview and may not extend to all types of Python packages. Si no se puede importar los módulos, intente publicar de nuevo con la opción --no-bundler.If you're unable to import your modules, try publishing again using the --no-bundler option.

func azure functionapp publish <app_name> --build-native-deps --no-bundler

Si sigue teniendo problemas, díganoslo; para ello, abra una incidencia e incluya una descripción del problema.If you continue to experience issues, please let us know by opening an issue and including a description of the problem.

Para compilar las dependencias y publicar con un sistema de entrega e integración continuas (CI-CD), puede usar una canalización de Azure o un script personalizado de Travis CI.To build your dependencies and publish using a continuous integration (CI) and continuous delivery (CD) system, you can use an Azure Pipeline or Travis CI custom script.

A continuación se muestra un ejemplo de script azure-pipelines.yml para el proceso de compilación y publicación.Following is an example azure-pipelines.yml script for the build and publishing process.

pool:
  vmImage: 'Ubuntu 16.04'

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '8.x'

- script: |
    set -e
    echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ wheezy main" | sudo tee /etc/apt/sources.list.d/azure-cli.list
    curl -L https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
    sudo apt-get install -y apt-transport-https
    echo "install Azure CLI..."
    sudo apt-get update && sudo apt-get install -y azure-cli
    npm i -g azure-functions-core-tools --unsafe-perm true
    echo "installing dotnet core"
    curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 2.0
- script: |
    set -e
    az login --service-principal --username "$(APP_ID)" --password "$(PASSWORD)" --tenant "$(TENANT_ID)" 
    func settings add FUNCTIONS_WORKER_RUNTIME python
    func extensions install
    func azure functionapp publish $(APP_NAME) --build-native-deps

A continuación se muestra un ejemplo de script .travis.yaml para el proceso de compilación y publicación.Following is an example .travis.yaml script for the build and publishing process.

sudo: required

language: node_js

node_js:
  - "8"

services:
  - docker

before_install:
  - echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ wheezy main" | sudo tee /etc/apt/sources.list.d/azure-cli.list
  - curl -L https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
  - sudo apt-get install -y apt-transport-https
  - sudo apt-get update && sudo apt-get install -y azure-cli
  - npm i -g azure-functions-core-tools --unsafe-perm true


script:
  - az login --service-principal --username "$APP_ID" --password "$PASSWORD" --tenant "$TENANT_ID"
  - az account get-access-token --query "accessToken" | func azure functionapp publish $APP_NAME --build-native-deps

Problemas conocidos y preguntas más frecuentesKnown issues and FAQ

Todos los problemas conocidos y las solicitudes de características se siguen mediante la lista deproblemas de GitHub.All known issues and feature requests are tracked using GitHub issues list. Si le surge algún problema y no lo encuentra en GitHub, abra un nuevo problema e incluya una descripción detallada del mismo.If you run into a problem and can't find the issue in GitHub, open a new issue and include a detailed description of the problem.

Pasos siguientesNext steps

Para obtener más información, consulte los siguientes recursos:For more information, see the following resources: