Azure ML Pipeline中PythonScriptStep的数据加载与处理答疑
Azure ML管道数据传输与管理疑问解答
1. 既然已通过Run上下文加载数据,为何data_prep.py脚本仍需设置命令行参数?
命令行参数的核心作用是传递数据集的关联标识和输出目录的实际路径,具体原因:
- 在管道定义里用
raw_ds.as_named_input('raw_data')时,传递给脚本的是数据集的运行时关联信息,Run上下文能找到run.input_datasets['raw_data'],正是因为这个参数完成了数据集的“名称映射”传递——如果省略该参数,Run上下文无法关联到指定的输入数据集。 - 输出路径
prepped_data是OutputFileDatasetConfig对象,管道运行时会在计算目标上生成临时挂载/存储路径,脚本必须通过命令行参数拿到这个路径,才知道预处理后的数据要写入哪里。 - 提升脚本灵活性:后续更换输入数据集、调整输出目录时,无需修改脚本代码,只需在管道定义里调整参数即可,脚本本身可复用在不同管道步骤中。
另外注意:脚本里定义的--raw-ds参数虽然接收了raw_dataset_id,但代码里没直接用这个变量——这是因为as_named_input已完成名称映射,Run上下文能直接通过raw_data获取数据集,但这个参数不能省略,否则管道无法完成数据集与脚本的关联。
2. 是否存在无需借助Run上下文的替代数据加载方式?
有两种常用替代方案:
方案一:直接传递数据集的本地路径
在管道定义中,将数据集转换为下载/挂载路径传递给脚本:
# 管道步骤定义修改 step1 = PythonScriptStep( name='prepare data', source_directory='scripts', script_name='data_prep.py', compute_target='aml-cluster', arguments=['--raw-ds-path', raw_ds.as_download(), # 直接传递下载后的本地路径 '--out_folder', prepped_data] )
脚本直接读取路径下的文件,无需Run上下文:
# data_prep.py 修改 import argparse import os import pandas as pd parser = argparse.ArgumentParser() parser.add_argument('--raw-ds-path', type=str, dest='raw_path') parser.add_argument('--out_folder', type=str, dest='folder') args = parser.parse_args() # 直接读取路径下的文件 raw_df = pd.read_csv(os.path.join(args.raw_path, 'raw_data.csv'))
方案二:使用Azure Storage SDK直接访问数据存储
如果数据集存储在Azure Blob/ADLS中,可在脚本里直接用azure-storage-blob或azure-storage-file-datalake SDK读取数据,但需确保计算目标有访问数据存储的权限(比如通过服务主体或托管标识)。这种方式适合需要精细控制数据访问的场景,但不如前一种简洁。
3. 若数据为非表格格式(例如JSON文件),应如何进行数据加载处理?
针对非表格数据,核心是先获取文件的本地路径,再用对应格式的读取工具处理:
方式一:借助Run上下文(FileDataset场景)
如果原始数据集是FileDataset(而非TabularDataset),可通过Run上下文获取文件路径后读取:
# data_prep.py 处理JSON文件 from azureml.core import Run import argparse import os import json run = Run.get_context() parser = argparse.ArgumentParser() parser.add_argument('--raw-ds', type=str, dest='raw_dataset_id') parser.add_argument('--out_folder', type=str, dest='folder') args = parser.parse_args() # 获取FileDataset并下载到本地 raw_file_dataset = run.input_datasets['raw_data'] download_path = raw_file_dataset.download() # 读取JSON文件 json_data = [] for file_path in download_path: if file_path.endswith('.json'): with open(file_path, 'r') as f: json_data.append(json.load(f)) # 处理后保存 os.makedirs(args.folder, exist_ok=True) output_path = os.path.join(args.folder, 'processed_data.json') with open(output_path, 'w') as f: json.dump(json_data, f)
方式二:直接通过命令行参数传递路径
和表格数据的替代方案类似,在管道里传递数据集的下载/挂载路径,脚本直接遍历路径下的JSON文件读取:
# data_prep.py 直接处理JSON路径 import argparse import os import json parser = argparse.ArgumentParser() parser.add_argument('--raw-ds-path', type=str, dest='raw_path') parser.add_argument('--out_folder', type=str, dest='folder') args = parser.parse_args() json_data = [] for root, dirs, files in os.walk(args.raw_path): for file in files: if file.endswith('.json'): with open(os.path.join(root, file), 'r') as f: json_data.append(json.load(f)) # 保存处理后的数据 os.makedirs(args.folder, exist_ok=True) output_path = os.path.join(args.folder, 'processed_data.json') with open(output_path, 'w') as f: json.dump(json_data, f)
内容的提问来源于stack exchange,提问作者João Areias
相关产品推荐
相关产品推荐

