Azure Python Function V2 编程模型即使在 Azure 中部署后也未显示功能

问题描述 投票:0回答:1

我想在 Python 中使用 Azure Function 部署 CRON 计时器触发器。我尝试使用 VS Code 部署它。

以下是我遵循的步骤:

第 1 步: 安装以下所有先决条件:

  1. 已安装 Azure Core Tools v4
  2. 已安装 Azurite V3 扩展。
  3. 使用 Python 3.11.8。
  4. Windows 中最新版本的 VS Code
  5. 已安装 Azure 功能扩展

第 2 步: 使用消费计划创建 Azure Python 函数

第 3 步: 使用 Python v2 模型创建函数应用程序

Used VS Code Azure Extension to create Function locally

步骤 4: 在默认函数代码中进行所需的更改后,我尝试通过选择所需的函数应用程序使用 VS Code Azure 扩展来部署该代码: Deployed using following Azure Extension

第 5 步: 检查部署状态。在VS Code中显示成功。在门户中,所有未被忽略的文件都会上传到 Azure 函数资源,但不会显示为函数。

Function is not showing up in overview

However I can see files successfully deployed in App File Section

第6步:我还检查了VS Code中部署的Azure Function,但在Function下看不到function.json。

Cross checked in VS Code

我的 function_app.py 如下所示:

import logging
import azure.functions as func
import traceback
import uuid
from tqdm import tqdm
import requests
from dotenv import load_dotenv
import os
from datetime import datetime,timedelta
import time
from dateutil.relativedelta import relativedelta
import inflect
import logging
######################################## VARIABLES ########################################
# Load environment variables from .env file
load_dotenv()
# Define authentication parameters for power platform datavese
tenant_id = os.environ.get('TenantId')
client_id = os.environ.get('ClientId')
client_secret = os.environ.get('ClientSecret')
resource = os.environ.get('Resource')

# Constants
MAX_RETRIES = 5  # Maximum number of retries
BASE_DELAY = 1.0  # Base delay in seconds for the exponential backoff
MAX_DELAY = 60.0  # Maximum delay in seconds for the exponential backoff
BATCH_SIZE = 1000  # Batch size for logging purposes
RATE_LIMIT = 6000  # Maximum number of requests per time window
TIME_WINDOW = 300  # Time window in seconds for rate limiting
CONCURRENT_REQUESTS = 100  # Maximum number of concurrent requests

# Audit Management Table
AuditManagement = os.environ.get('AuditManagement')

# Endpoint    
odata_endpoint = f"{resource}/api/data/v9.2/"
# Date variables
date_today = datetime.utcnow()
# Prefixes
prefixes = os.environ.get("Prefixes").split(",")
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Handle Error
def handle_error(exception):
    print(f"An error occurred: {exception}")

######################################## Fetch Token ########################################
def fetchToken():
    token_url = f'https://login.microsoftonline.com/{tenant_id}/oauth2/token'
    #print("app_registration_token_url :",token_url)
    token_data = {
        'grant_type': 'client_credentials',
        'client_id': client_id,
        'client_secret': client_secret,
        'resource': resource
    }
    token_response = requests.post(token_url, data=token_data)
    #print("token_response",token_response)
    access_token = token_response.json()['access_token']
    print("access_token : ",access_token)
    return access_token

######################################## Fetch Audit Management Table ########################################
headers = {
        "Authorization": f"Bearer {fetchToken()}",
        "Accept": "application/json",
        "Content-Type": "application/json"
    }
post_headers = {
    'Authorization': f'Bearer {fetchToken()}',
    'OData-MaxVersion': '4.0',
    'OData-Version': '4.0',
    'Accept': 'application/json',
    'If-None-Match': 'null'
}
def fetch_audit_management():
    logging.info(f'------------Table Records--------------------')
    try:
        full_url = f"{odata_endpoint + AuditManagement}"
        print("full_url : ",full_url)
        response = requests.get(full_url, headers=headers)
        if response.status_code == 200:
            data = response.json()
            records = data.get("value", [])
            if not records:
                print("No records fetched for While Active")
                logging.info("No records fetched for While Active")
                return("No records fetched")
            else:
                logging.info("Records fetched for While Active")
                return records
        else:
            logging.info(f"Failed to retrieve records. Status code: {response.status_code}")
            print(f"Failed to retrieve records. Status code: {response.status_code}")
    except Exception as e:
        handle_error(e)
        return None  # Return None when an error occurs

 
app = func.FunctionApp()
@app.schedule(schedule="0 0 4 * * *", arg_name="myTimer", run_on_startup=False,
              use_monitor=False)
def amr_timer_trigger(myTimer: func.TimerRequest) -> None:
    start_time = time.time()
    # Log the start of Azure Function execution in hh:mm:ss format
    logging.info(f'timer trigger function executed at: {time.strftime("%H:%M:%S")}')
    if myTimer.past_due:
        logging.info('The timer is past due!')
    else:
        try:
        ###### Comment : Fetching while active entity from  Table
            logging.info(f'\n\nFetching while active entity from Table')
            records = fetch_audit_management()

            # Iterating over entites fetched
            logging.info(f'Iterating over entites fetched from Table')
            for record in records:    
                logging.info(f'\n\nFetched Records: {record}')
        except Exception as e:
            handle_error(e)

    logging.info('AMR timer trigger function executed in %s seconds', time.time() - start_time)

需求.txt

azure-functions
python-dotenv
requests
python-dateutil
inflect
tqdm

local.settings.json

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsFeatureFlags": "EnableWorkerIndexing"
  }
}

任何帮助或建议将不胜感激,因为我想可靠地测试部署。

我尝试了上述所有步骤。预期结果是 Azure Function 部署成功。

azure azure-functions azure-python-sdk azure-triggers timer-trigger
1个回答
0
投票
  • 确保您已在
    local.settings.json
    中添加了所有必需的应用程序设置。
  • 添加存储连接字符串作为
    "AzureWebJobsStorage"
    设置的值。
"AzureWebJobsFeatureFlags": "EnableWorkerIndexing"

local.settings.json:

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
    "AzureWebJobsStorage": "<Storage_connection_string>"
  }
}
  • 确保您已在 Azure Function App 中添加所有环境变量。

主机.json:

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  }
}
  • 将所有必需的包包含在requirements.txt中。

  • 创建一个新的虚拟环境并使用以下命令激活:

py -m venv env
.\env\Scripts\activate

使用以下命令安装软件包:

pip install -r requirements.txt
  • 在本地运行该函数。

使用以下命令再次将函数部署到Azure Function App(消费计划):

func azure functionapp publish <functionapp_name>

  • 部署日志:
Getting site publishing info...
[2024-04-11T12:10:06.519Z] Starting the function app deployment...
Creating archive for current directory...
Performing remote build for functions project.
Deleting the old .python_packages directory
Uploading 5.88 KB [###############################################################################]
Remote build in progress, please wait...
Updating submodules.
Preparing deployment for commit id '7b5c575a-0'.
PreDeployment: context.CleanOutputPath False
PreDeployment: context.OutputPath /home/site/wwwroot
Repository path is /tmp/zipdeploy/extracted
Running oryx build...
Command: oryx build /tmp/zipdeploy/extracted -o /home/site/wwwroot --platform python --platform-version 3.11 -p packagedir=.python_packages/lib/site-packages
Operation performed by Microsoft Oryx, https://github.com/Microsoft/Oryx
You can report issues at https://github.com/Microsoft/Oryx/issues

Oryx Version: 0.2.20230210.1, Commit: a49c8f6b8abbe95b4356552c4c884dea7fd0d86e, ReleaseTagName: 20230210.1

Build Operation ID: 65736983f855799a
Repository Commit : 7b5c575a-0ef2-43ba-b475-cbb121978b71
OS Type           : bullseye
Image Type        : githubactions

Detecting platforms...
Detected following platforms:
  python: 3.11.8
Version '3.11.8' of platform 'python' is not installed. Generating script to install it...


Source directory     : /tmp/zipdeploy/extracted
Destination directory: /home/site/wwwroot


Downloading and extracting 'python' version '3.11.8' to '/tmp/oryx/platforms/python/3.11.8'...
Detected image debian flavor: bullseye.
Downloaded in 3 sec(s).
Verifying checksum...
Extracting contents...
performing sha512 checksum for: python...
Done in 7 sec(s).

image detector file exists, platform is python..
OS detector file exists, OS is bullseye..
Python Version: /tmp/oryx/platforms/python/3.11.8/bin/python3.11
Creating directory for command manifest file if it does not exist
Removing existing manifest file

Running pip install...
Done in 5 sec(s).
[12:10:19+0000] Collecting azure-functions
[12:10:19+0000]   Downloading azure_functions-1.18.0-py3-none-any.whl (173 kB)
[12:10:19+0000] Collecting python-dotenv
[12:10:19+0000]   Downloading python_dotenv-1.0.1-py3-none-any.whl (19 kB)
[12:10:19+0000] Collecting requests
[12:10:19+0000]   Downloading requests-2.31.0-py3-none-any.whl (62 kB)
[12:10:19+0000] Collecting python-dateutil
[12:10:19+0000]   Downloading python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB)
[12:10:20+0000] Collecting inflect
[12:10:20+0000]   Downloading inflect-7.2.0-py3-none-any.whl (34 kB)
[12:10:20+0000] Collecting tqdm
[12:10:20+0000]   Downloading tqdm-4.66.2-py3-none-any.whl (78 kB)
[12:10:20+0000] Collecting urllib3<3,>=1.21.1
[12:10:20+0000]   Downloading urllib3-2.2.1-py3-none-any.whl (121 kB)
[12:10:20+0000] Collecting charset-normalizer<4,>=2
[12:10:20+0000]   Downloading charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (140 kB)
[12:10:20+0000] Collecting idna<4,>=2.5
[12:10:20+0000]   Downloading idna-3.7-py3-none-any.whl (66 kB)
[12:10:20+0000] Collecting certifi>=2017.4.17
[12:10:21+0000]   Downloading certifi-2024.2.2-py3-none-any.whl (163 kB)
[12:10:21+0000] Collecting six>=1.5
[12:10:21+0000]   Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
[12:10:21+0000] Collecting more-itertools
[12:10:21+0000]   Downloading more_itertools-10.2.0-py3-none-any.whl (57 kB)
[12:10:21+0000] Collecting typeguard>=4.0.1
[12:10:21+0000]   Downloading typeguard-4.2.1-py3-none-any.whl (34 kB)
[12:10:21+0000] Collecting typing-extensions
[12:10:21+0000]   Downloading typing_extensions-4.11.0-py3-none-any.whl (34 kB)
[12:10:21+0000] Installing collected packages: typing-extensions, urllib3, typeguard, six, more-itertools, idna, charset-normalizer, certifi, tqdm, requests, python-dotenv, python-dateutil, inflect, azure-functions
[12:10:22+0000] Successfully installed azure-functions-1.18.0 certifi-2024.2.2 charset-normalizer-3.3.2 idna-3.7 inflect-7.2.0 more-itertools-10.2.0 python-dateutil-2.9.0.post0 python-dotenv-1.0.1 requests-2.31.0 six-1.16.0 tqdm-4.66.2 typeguard-4.2.1 typing-extensions-4.11.0 urllib3-2.2.1
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 21.2.4; however, version 24.0 is available.
You should consider upgrading via the '/tmp/oryx/platforms/python/3.11.8/bin/python3.11 -m pip install --upgrade pip' command.
Not a vso image, so not writing build commands
Preparing output...

Copying files to destination directory '/home/site/wwwroot'...
Done in 0 sec(s).

Removing existing manifest file
Creating a manifest file...
Manifest file created.
Copying .ostype to manifest output directory.

Done in 12 sec(s).
Running post deployment command(s)...

Generating summary of Oryx build
Deployment Log file does not exist in /tmp/oryx-build.log
The logfile at /tmp/oryx-build.log is empty. Unable to fetch the summary of build
Triggering recycle (preview mode disabled).
Linux Consumption plan has a 1.5 GB memory limit on a remote build container.
To check our service limit, please visit https://docs.microsoft.com/en-us/azure/azure-functions/functions-scale#service-limits
Writing the artifacts to a squashfs file
Parallel mksquashfs: Using 1 processor
Creating 4.0 filesystem on /home/site/artifacts/functionappartifact.squashfs, block size 131072.

[===============================================================|] 557/557 100%

Exportable Squashfs 4.0 filesystem, gzip compressed, data block size 131072
        compressed data, compressed metadata, compressed fragments,
        compressed xattrs, compressed ids
        duplicates are removed
Filesystem size 2325.05 Kbytes (2.27 Mbytes)
        33.37% of uncompressed filesystem size (6968.27 Kbytes)
Inode table size 5860 bytes (5.72 Kbytes)
        28.89% of uncompressed inode table size (20286 bytes)
Directory table size 5651 bytes (5.52 Kbytes)
        36.05% of uncompressed directory table size (15675 bytes)
Number of duplicate files found 33
Number of inodes 631
Number of files 560
Number of fragments 47
Number of symbolic links  0
Number of device nodes 0
Number of fifo nodes 0
Number of socket nodes 0
Number of directories 71
Number of ids (unique uids + gids) 1
Number of uids 1
        root (0)
Number of gids 1
        root (0)
Creating placeholder blob for linux consumption function app...
SCM_RUN_FROM_PACKAGE placeholder blob scm-latest-kpyfn.zip located
Uploading built content /home/site/artifacts/functionappartifact.squashfs for linux consumption function app...
Resetting all workers for kpyfn.azurewebsites.net
Deployment successful. deployer = Push-Deployer deploymentPath = Functions App ZipDeploy. Extract zip. Remote build.
Remote build succeeded!
© www.soinside.com 2019 - 2024. All rights reserved.