Azure Runbook中Python 3.8脚本执行时出现ModuleNotFoundError: No module named 'azure.profiles'的解决咨询
Azure Runbook中Python 3.8脚本执行时出现ModuleNotFoundError: No module named 'azure.profiles'的解决咨询
我目前尝试在Azure Runbook的Python 3.8运行时环境中执行一个Python脚本,目的是监控虚拟机状态,发送邮件(最小可复现示例中未包含此部分),同时通过调用generate_incident_reference_number()方法的装饰器生成一个UUID4格式的GUID。
我已经通过Home > App Registrations注册了服务主体,获取到了tenant_id、client_id和client_secret,也查阅了Azure SDK文档资源,并将以下.whl包上传到了我的Automation Account > Shared Resources > Python Packages中:
azure_core == 1.32.0 azure_identity == 1.19.0 azure_mgmt_compute == 34.0.0 azure_mgmt_core == 1.5.0 azure_mgmt_resource 23.2.0
每当我通过Home > AutomationAccount > Process Automation > Runbooks >
Failed Traceback (most recent call last): File "/usr/src/tmp/2e1ee55b-678c-4023-8759-4e290498c63c/runbooks/vm-monitor-logging.py", line 12, in <module> from azure.mgmt.compute import ComputeManagementClient File "C:\userenv\lib\site-packages\azure\mgmt\compute\__init__.py", line 9, in <module> from ._compute_management_client import ComputeManagementClient File "C:\userenv\lib\site-packages\azure\mgmt\compute\_compute_management_client.py", line 18, in <module> from azure.profiles import KnownProfiles, ProfileDefinition ModuleNotFoundError: No module named 'azure.profiles'
我觉得问题应该是ComputeManagementClient依赖的azure.profiles模块缺失,但我已经导入了ComputeManagementClient,搞不懂为什么会出现这个问题。
以下是我的最小可复现示例代码:
import time import smtplib import json import base64 import hashlib import hmac import requests import uuid from datetime import datetime, timezone from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from azure.mgmt.compute import ComputeManagementClient from azure.identity import ClientSecretCredential from functools import wraps # Azure subscription SUBSCRIPTION_ID = 'xxx' # Azure Resources resource_group_name = 'xxx' vm_name = 'xxx' # Logs Workspace Information LOGS_WORKSPACE_ID = "xxx" LOGS_WORKSPACE_KEY = "xxx" LOGS_API_ENDPOINT_REGION = "xxx" # Data Collection Endpoint DATA_COLLECTION_ENDPOINT = f"https://vmstatusdce-o0w0.{LOGS_API_ENDPOINT_REGION}-1.ingest.monitor.azure.com" def execution_trace(func) -> str: """Collects the name of the function where the issue, error or degradation resides.""" @wraps(func) def wrapper(*args, **kwargs): calling_function = f"Source: def {func.__name__}()" try: return func(*args, **kwargs, calling_function = calling_function) except Exception as e: print(f"There was an error in returning the name of the function. Logs available {e}") return wrapper def assign_log_number(func) -> str: """Generates a log reference number, which will be sent to Azure Monitor portal.""" @wraps(func) def wrapper(*args, **kwargs): assign_log_number = generate_incident_reference_number() custom_message = None try: return func(*args, **kwargs, assign_log_number = assign_log_number) except TypeError as e: custom_message = f"There was a TypeError Exception associated with assigning the Azure log number {e}" except Exception as e: custom_message = f"There was an error in generating a log reference. Logs available {e}" if custom_message: print(custom_message) return wrapper # Azure Authentication @execution_trace @assign_log_number def service_principal_authentication(calling_function:str = None, assign_log_number = None) -> ComputeManagementClient | None: """Checks the Authentication of Azure's Service Principal""" custom_message = None try: credentials = ClientSecretCredential( client_id = 'xxx', tenant_id = 'xxx', client_secret = 'xxx' ) return ComputeManagementClient(credentials, SUBSCRIPTION_ID) #except ClientAuthenticationError as e: # custom_message = f"Client Authentication Error {e} | {calling_function}" except Exception as e: custom_message = f"There was an error in authenticating the Service Principal {e} | {calling_function}." if custom_message: print(custom_message) def generate_incident_reference_number() -> str: """Generate an incident reference number to be logged in the Azure monitoring logs, using Python's built-in UUID module. UUID4 is applied.""" """Generates a universally unique identifier (UUID) to be used as a log number. UUID version 4 is used.""" return f"{uuid.uuid4()}" def generate_authentication_signature(workspace_id:str, workspace_key:str, body) -> list[str,str]: """Generates the signature needed for authenticating the request.""" date = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT') content_length = str(len(body)) # Prepare the string to sign string_to_sign = f"POST\n{content_length}\napplication/json\nx-ms-date:{date}\n/api/logs" # Generate the signature using HMAC and SHA256 signature = base64.b64encode( hmac.new( base64.b64decode(workspace_key), string_to_sign.encode('utf-8'), hashlib.sha256 ).digest() ).decode('utf-8') # Prepare the request headers headers = { "Content-Type" : "application/json", "Authorization" : f"SharedKey {workspace_id}:{signature}", "x-ms-date" : date, "Log-Type" : "CustomLogs" } return headers @execution_trace @assign_log_number def log_to_azure_monitor(new_vm_status:str, calling_function:str = None, assign_log_number:str = None) -> None: """Logs the incident data to Azure Monitor via HTTP Data Collector API. Disgreard Log Number data""" log_data = [{ "TimeGenerated" : datetime.now(timezone.utc).isoformat(), "VMName" : vm_name, "VMStatus" : new_vm_status, "LogNumber" : assign_log_number, }] # Convert log data to JSON format body = json.dumps(log_data) # Generate the headers with the signature headers = generate_authentication_signature(LOGS_WORKSPACE_ID, LOGS_WORKSPACE_KEY, body) # Azure Monitor HTTP API endpoint LOGS_API_ENDPOINT = f"https://{LOGS_WORKSPACE_ID}.ods.opinsights.azure.com/api/logs?api-version=2016-04-01" # Send the POST request to the Azure Monitor API custom_message = None try: response = requests.post(LOGS_API_ENDPOINT, headers=headers, data=body) if response.status_code == 200: custom_message = f"There is a new status to the VM {vm_name}: {new_vm_status}." else: custom_message = f"There was an error logging to Azure. Logging error {response.status_code}, Response: {response.text}" except Exception as e: custom_message = f"There was an error in the request retrieval. Logs available: {e}" if custom_message: print(custom_message) return def main() -> None: previous_vm_status = None while True: compute_client = service_principal_authentication() current_vm_status = get_vm_status(compute_client) if current_vm_status != previous_vm_status: log_to_azure_monitor(current_vm_status) previous_vm_status = current_vm_status time.sleep(300) if __name__ == "__main__": main()
请问我需要安装哪些依赖包,或者对脚本做哪些修改才能解决azure.profiles模块找不到的问题?
非常感谢!
备注:内容来源于stack exchange,提问作者TheFlyingPrussian
相关产品推荐
相关产品推荐

