如何在Azure ML计算实例中使用Python SDK1连接工作区?
问题概况
现有脚本可在本地(交互式认证)和实验Cluster Instances中正常连接Azure ML Workspace,但在Compute Instances中失效。原脚本依赖Run.get_context()判断环境并获取Workspace:
from azureml.core import Workspace from azureml.core.run import Run, _OfflineRun run = Run.get_context() if isinstance(run, _OfflineRun): workspace = Workspace( "subscription_id", "resource_group", "workspace_name", ) else: workspace = run.experiment.workspace
尝试使用MSIAuthentication时触发JSON解码错误,代码及报错如下:
from azureml.core.authentication import MsiAuthentication from azureml.core import Workspace msi_auth = MsiAuthentication() workspace = Workspace( "subscription_id", "resource_group", "workspace_name", auth=msi_auth, )
File ~/localfiles/.venv/lib/python3.8/site-packages/azureml/_vendor/azure_cli_core/auth/adal_authentication.py:65, in MSIAuthenticationWrapper.set_token(self)
63 from azureml._vendor.azure_cli_core.azclierror import AzureConnectionError, AzureResponseError
64 try:
---> 65 super(MSIAuthenticationWrapper, self).set_token()
66 except requests.exceptions.ConnectionError as err:
67 logger.debug('throw requests.exceptions.ConnectionError when doing MSIAuthentication: \n%s',
68 traceback.format_exc())
File ~/localfiles/.venv/lib/python3.8/site-packages/msrestazure/azure_active_directory.py:596, in MSIAuthentication.set_token(self)
594 def set_token(self):
595 if _is_app_service():
---> 596 self.scheme, _, self.token = get_msi_token_webapp(self.resource, self.msi_conf)
597 elif "MSI_ENDPOINT" in os.environ:
598 self.scheme, _, self.token = get_msi_token(self.resource, self.port, self.msi_conf)
File ~/localfiles/.venv/lib/python3.8/site-packages/msrestazure/azure_active_directory.py:548, in get_msi_token_webapp(resource, msi_conf)
546 raise RuntimeError(err_msg)
547 _LOGGER.debug('MSI: token retrieved')
---> 548 token_entry = result.json()
549 return token_entry['token_type'], token_entry['access_token'], token_entry
File ~/localfiles/.venv/lib/python3.8/site-packages/requests/models.py:975, in Response.json(self, **kwargs)
971 return complexjson.loads(self.text, **kwargs)
972 except JSONDecodeError as e:
973 # Catch JSON-related errors and raise as requests.JSONDecodeError
974 # This aliases json.JSONDecodeError and simplejson.JSONDecodeError
---> 975 raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
核心原因
Compute Instance与Cluster Instances的身份管理逻辑存在差异:
- Cluster Instances运行批量实验作业时,会自动绑定实验Run上下文,
run.experiment.workspace可正常解析Workspace - Compute Instance为交互式开发环境,
Run.get_context()返回的并非关联实验的Run对象,导致run.experiment.workspace无法生效;无参数MSIAuthentication因缺少特定身份参数(如client_id)或环境变量配置问题触发解码错误。
解决方案(无需迁移至SDK v2)
方案1:使用Workspace.from_config()自动认证
Compute Instance默认会在用户目录~/.azureml/config.json生成Workspace配置文件,直接通过以下代码即可自动使用托管身份完成认证,无需硬编码ID或手动处理身份:
from azureml.core import Workspace try: workspace = Workspace.from_config() except Exception: # 若config.json不存在,手动指定参数适配本地/CI环境 workspace = Workspace( subscription_id="your_sub_id", resource_group="your_rg", workspace_name="your_workspace_name" )
方案2:修正Run上下文判断逻辑
针对Compute Instance的交互式环境,扩展判断逻辑,捕获run.experiment无法访问的情况,降级到本地认证方式:
from azureml.core import Workspace from azureml.core.run import Run, _OfflineRun run = Run.get_context() try: if isinstance(run, _OfflineRun): # 本地离线环境使用交互式认证 workspace = Workspace( "your_sub_id", "your_rg", "your_workspace_name" ) else: # 尝试从Run上下文获取Workspace,失败则切换到config认证 workspace = run.experiment.workspace except AttributeError: workspace = Workspace.from_config()
方案3:正确配置MSIAuthentication
若必须使用MSI认证,需指定Compute Instance系统分配MSI的client_id(可在Azure门户的Compute Instance身份页面获取):
from azureml.core.authentication import MsiAuthentication from azureml.core import Workspace # 替换为你的Compute Instance MSI的client_id msi_auth = MsiAuthentication(client_id="your_compute_instance_msi_client_id") workspace = Workspace( subscription_id="your_sub_id", resource_group="your_rg", workspace_name="your_workspace_name", auth=msi_auth )
内容的提问来源于stack exchange,提问作者BeGreen

