如何持续交付部署在 Azure 中的 python 函数应用程序?

How to make a continuous delivery of a python function app deployed in Azure?

我第一次使用部署管道将 Python 函数应用程序部署到 Azure:

https://docs.microsoft.com/bs-latn-ba/azure/azure-functions/functions-how-to-azure-devops

包已使用 Kudu Zip 部署部署到 Azure。

我的 http 触发函数在本地运行得很好(在 Windows 上),但我在 Azure 上有 500 个内部错误,因为它找不到模块 requests

Exception: ModuleNotFoundError: No module named 'requests'

进口__init__.py:

import logging, requests, os
import azure.functions as func

如果我删除 'requests' 依赖项,该函数将在 Azure 上运行(状态 200)。

请求库由 requirement.txt 导入并通过构建管道复制到 .venv36/lib/site-packages/requests。

所以我想知道在包中构建的虚拟环境.venv36是否被部署在Azure中的功能使用。没有关于如何在 Azure 中激活虚拟环境的说明。

您需要分别处理这 2 个导入,

import azure.functions as func
import requests

希望我能正确理解你的问题。

当您在本地计算机上安装时,库会安装在 python 所在的位置(或至少安装在实际代码所在位置以外的位置)。这意味着,当您打包代码时,实际上并没有将库放在一起。

要解决这个问题,您可以使用虚拟环境。 Python 提供一个 venv 工具(还有一个标准的 linux 虚拟环境工具),您可以 运行 通过:

python -m venv /path/to/my/dir
source /path/to/my/dir/bin/activate 
cd /path/to/my/dir/bin/activate
pip install -r requirements.txt
deactivate

我知道你提到了 windows,所以我建议使用 WSL 和 ubuntu 图像(通常是一个很好的工具)。可能有一种方法可以在 windows 中工作,否则虽然我不知道。

编辑:固定格式

如果您将虚拟环境命名为 worker_venv,就像您链接的文档中所命名的那样,它应该可以工作(假设您正在为您的管道使用 Linux 环境)。

但是,Python Azure Functions 文档将很快更新,推荐的方法是不要从部署管道部署整个虚拟环境。 相反,您希望在 .python_packages/lib/site-packages.

中安装您的软件包

你可以做 --

pip3.6 install --target .python_packages/lib/site-packages -r requirements.txt

而不是--

python3.6 -m venv worker_venv
source worker_venv/bin/activate
pip3.6 install setuptools
pip3.6 install -r requirements.txt

它应该可以正常工作。

我们在使用最新版本的 YAML 管道模板时也遇到了同样的问题:

- task: UsePythonVersion@0
  displayName: 'Use Python 3.6'
  inputs:
    versionSpec: 3.6 # Functions V2 supports Python 3.6 as of today

- bash: |
    python -m venv worker_venv
    source worker_venv/bin/activate
    pip install -r requirements.txt
  workingDirectory: $(workingDirectory)
  displayName: 'Install application dependencies'

删除虚拟环境步骤,部署 Function App 并且 运行 没有任何问题。这似乎不是 Python 最佳实践;但是,这是我们唯一可以做的事情,以便在 Azure DevOps Pipelines 上正确部署它。

另外,在进行此更改之前,我们能够使用 Visual Studio 代码插件进行部署,这表明这是一个环境问题。

来自 Microsoft 的更新文档 (1/12/2020)

https://docs.microsoft.com/en-us/azure/azure-functions/functions-how-to-azure-devops?tabs=python

azure-pipelines.yml(我们在 Azure DevOps Pipelines 上的工作版本)

- master

variables:
  # Azure Resource Manager connection created during pipeline creation
  azureSubscription: '<subscription-id>'

  # Function app name
  functionAppName: '<built-function-app-name>'

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

  # Working Directory
  workingDirectory: '$(System.DefaultWorkingDirectory)/__app__'

stages:
- stage: Build
  displayName: Build stage

  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)

    steps:
    - bash: |
        if [ -f extensions.csproj ]
        then
            dotnet build extensions.csproj --runtime ubuntu.16.04-x64 --output ./bin
        fi
      workingDirectory: $(workingDirectory)
      displayName: 'Build extensions'

    - task: UsePythonVersion@0
      displayName: 'Use Python 3.7'
      inputs:
        versionSpec: 3.7 # Functions V2 supports Python 3.6 as of today

    - bash: |
        pip install --upgrade pip
        pip install --target="./.python_packages/lib/site-packages" -r ./requirements.txt
      workingDirectory: $(workingDirectory)
      displayName: 'Install application dependencies'

    - task: ArchiveFiles@2
      displayName: 'Archive files'
      inputs:
        rootFolderOrFile: '$(workingDirectory)'
        includeRootFolder: false
        archiveType: zip
        archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
        replaceExistingArchive: true

    - publish: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
      artifact: drop

- stage: Deploy
  displayName: Deploy stage
  dependsOn: Build
  condition: succeeded()

  jobs:
  - deployment: Deploy
    displayName: Deploy
    environment: 'production'
    pool:
      vmImage: $(vmImageName)

    strategy:
      runOnce:
        deploy:

          steps:
          - task: AzureFunctionApp@1
            displayName: 'Azure functions app deploy'
            inputs:
              azureSubscription: '$(azureSubscription)'
              appType: functionAppLinux
              appName: $(functionAppName)
              package: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'

虽然很旧但是:

*pip(python 版本) install --target .python_packages/lib/site-packages -r requirements.txt

例如。如果您使用 3.7 那么 pip3.7 install --target .python_packages/lib/site-packages -r requirements.txt

很有魅力

确实需要更明确地指出,部署 Azure Functions 时 Python 包的正确目录是 .python_packages/lib/site-packages。我必须深入研究 Azure Function Core Tools 源代码才能看到 where they put Python packages

还必须在 Function 调试控制台中四处挖掘以查看 Oryx 从何处获取包。

我猜 Version 3.7 YAML file here 中有一个指针,但没有标注目录的重要性,它是否适用于 Python 3.8 函数?

如果我没记错的话,这是使用 DevOps 部署 Python 函数的要求(除非您想安装 Function Core Tools 作为构建管道的一部分!)。