Azure Functions Python 开发人员指南Azure Functions Python developer guide

本文介绍了如何使用 Python 开发 Azure Functions。This article is an introduction to developing Azure Functions using Python. 以下内容假定你已阅读 Azure Functions 开发人员指南The content below assumes that you've already read the Azure Functions developers guide.

Note

用于 Azure Functions 的 Python 当前为预览版。Python for Azure Functions is currently in preview. 若要接收重要更新,请订阅 GitHub 上的 Azure 应用服务公告存储库。To receive important updates, subscribe to the Azure App Service announcements repository on GitHub.

编程模型Programming model

Azure 函数应是 Python 脚本中处理输入并生成输出的无状态方法。An Azure Function should be a stateless method in your Python script that processes input and produces output. 默认情况下,运行时期望此函数在 __init__.py 文件中作为名为 main() 的全局方法实现。By default, the runtime expects this to be implemented as a global method called main() in the __init__.py file.

可以通过在 function.json 文件中指定 scriptFileentryPoint 属性来更改默认配置。You can change the default configuration by specifying the scriptFile and entryPoint properties in the function.json file. 例如,下面的 function.json 指示运行时使用 main.py 文件中的 customentry() 方法作为 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",
  ...
}

来自触发器和绑定的数据使用在 function.json 配置文件中定义的 name 属性,通过方法特性绑定到函数。Data from triggers and bindings is bound to the function via method attributes using the name property defined in the function.json configuration file. 例如,下面的 function.json 描述一个由名为 req 的 HTTP 请求触发的简单函数: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"
    }
  ]
}

__init__.py 文件包含以下函数代码:The __init__.py file contains the following function code:

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

(可选)还可以使用 Python 类型注释在函数中声明参数类型和返回类型。Optionally, you can also declare the parameter types and return type in the function using Python type annotations. 例如,可以按如下所示,使用注释编写相同的函数: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}!'

使用 azure.functions.* 包中附带的 Python 注释将输入和输出绑定到方法。Use the Python annotations included in the azure.functions.* package to bind input and outputs to your methods.

文件夹结构Folder structure

Python 函数项目的文件夹结构如下所示: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

有一个共享的 host.json 文件,可用于配置函数应用。There's a shared host.json file that can be used to configure the function app. 每个函数都有自己的代码文件和绑定配置文件 (function.json)。Each function has its own code file and binding configuration file (function.json).

共享代码应保留在单独的文件夹中。Shared code should be kept in a separate folder. 若要引用 SharedCode 文件夹中的模块,可以使用以下语法:To reference modules in the SharedCode folder, you can use the following syntax:

from ..SharedCode import myFirstHelperFunction

Functions 运行时使用的绑定扩展在 extensions.csproj 文件中定义,实际库文件位于 bin 文件夹中。Binding extensions used by the Functions runtime are defined in the extensions.csproj file, with the actual library files in the bin folder. 本地开发时,必须使用 Azure Functions Core Tools 注册绑定扩展When developing locally, you must register binding extensions using Azure Functions Core Tools.

在 Azure 中将 Functions 项目部署到函数应用时,FunctionApp 文件夹的整个内容应包含在包中,但不包含该文件夹本身。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.

输入Inputs

在 Azure Functions 中,输入分为两种类别:触发器输入和附加输入。Inputs are divided into two categories in Azure Functions: trigger input and additional input. 虽然它们在 function.json 中并不相同,但它们在 Python 代码中的使用方法却是相同的。Although they are different in function.json, the usage is identical in Python code. 请看以下代码片段示例:Let's take the following code snippet as an example:

{
  "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"
    }
  ]
}
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()}')

调用函数时,HTTP 请求作为 req 传递给函数。When the function is invoked, the HTTP request is passed to the function as req. 将基于路由 URL 中的 id 从 Azure Blob 存储检索一个条目,并在函数体中用作 objAn 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.

OutputsOutputs

输出可以在返回值和输出参数中进行表示。Output can be expressed both in return value and output parameters. 如果只有一个输出,则建议使用返回值。If there's only one output, we recommend using the return value. 对于多个输出,必须使用输出参数。For multiple outputs, you'll have to use output parameters.

若要使用函数的返回值作为输出绑定的值,则绑定的 name 属性应在 function.json 中设置为 $returnTo 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.

若要生成多个输出,请使用 azure.functions.Out 接口提供的 set() 方法将值分配给绑定。To produce multiple outputs, use the set() method provided by the azure.functions.Out interface to assign a value to the binding. 例如,以下函数可以将消息推送到队列,还可返回 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

将共享代码导入函数模块中Importing shared code into a function module

与函数模块一起发布的 Python 模块必须使用相关导入语法进行导入: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)

或者,将共享代码置于独立包中,将它发布到公共或专用 PyPI 实例,并将它指定为常规依赖项。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.

异步Async

由于对于每个函数应用只能存在单个 Python 进程,因此建议使用 async def 语句将 Azure 函数实现为异步协同程序。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()

如果 main() 函数是同步函数(无 async 限定符),则我们会在 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()

上下文Context

若要在执行过程中获取函数的调用上下文,请在其签名中包含 context 参数。To get the invocation context of a function during execution, include the context argument in its signature.

例如:For example:

import azure.functions

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

Context 类具有以下方法:The Context class has the following methods:

function_directory
在其中运行函数的目录。The directory in which the function is running.

function_name
函数的名称。Name of the function.

invocation_id
当前函数调用的 ID。ID of the current function invocation.

Python 版本和包管理Python version and package management

当前,Azure Functions 仅支持 Python 3.6.x(CPython 正式分发版)。Currently, Azure Functions only supports Python 3.6.x (official CPython distribution).

在使用 Azure Functions Core Tools 或 Visual Studio Code 进行本地开发时,将所需包的名称和版本添加到 requirements.txt 文件并使用 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.

例如,可以使用以下要求文件和 pip 命令从 PyPI 安装 requests 包。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

准备好进行发布时,确保所有依赖项都在 requirements.txt 文件(位于项目目录的根目录)中列出。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. 若要成功执行 Azure Functions,要求文件应至少包含以下包: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

发布到 AzurePublishing to Azure

如果使用的包需要编译器并且不支持从 PyPI 安装 manylinux 兼容滚轮的包,则发布到 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

若要自动生成并配置所需二进制文件,请在本地计算机上安装 Docker并运行以下命令以使用 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). 请记住将 <app name> 替换为 Azure 中的函数应用名称。Remember to replace <app name> with the name of your function app in Azure.

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

实际上,Core Tools 会使用 docker 将 mcr.microsoft.com/azure-functions/python 映像作为本地计算机上的容器来运行。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. 它随后会使用此环境从源分发版生成并安装所需模块,然后再打包它们以便最终部署到 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.

Note

Core Tools (func) 使用 PyInstaller 程序将用户的代码和依赖项冻结到单个独立可执行文件中以在 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. 此功能当前处于预览状态,可能不会扩展到所有类型的 Python 包。This functionality is currently in preview and may not extend to all types of Python packages. 如果无法导入模块,请使用 --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

如果继续遇到问题,请通过建立问题并包含问题描述来告知我们。If you continue to experience issues, please let us know by opening an issue and including a description of the problem.

若要使用持续集成 (CI) 和持续交付 (CD) 系统生成依赖项并进行发布,可以使用 Travis CI 自定义脚本To build your dependencies and publish using a continuous integration (CI) and continuous delivery (CD) system, you can use Travis CI custom script.

下面是生成和发布过程的示例 .travis.yaml 脚本。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

已知问题和常见问题解答Known issues and FAQ

所有已知问题和功能请求都使用 GitHub 问题列表进行跟踪。All known issues and feature requests are tracked using GitHub issues list. 如果遇到 GitHub 中未列出的问题,请打开“新问题”并提供问题的详细说明。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.

后续步骤Next steps

有关详细信息,请参阅以下资源:For more information, see the following resources: