嵌套RSUBMIT中SAS宏变量传递失败问题求助
SAS嵌套RSUBMIT宏变量传递问题求解
在编写包含嵌套RSUBMIT的SAS模拟代码时,宏内部的嵌套RSUBMIT无法正确传入/传出宏变量。测试场景如下:
- 初始定义宏变量
A和B - 将
A传入第一个RSUBMIT,通过DATA步生成宏变量C,此过程正常 - 尝试将
B传入嵌套的第二个RSUBMIT,同样用DATA步生成宏变量D,但运行日志出现WARNING: Apparent symbolic reference B not resolved.警告,B无法被正确识别,导致D生成失败
测试代码
options mprint mlogic symbolgen; %let a = 1; %let b = 2; %put check1 &=a.; %put check1 &=b.; %macro run_outline(); %put check2 &=a.; %put check2 &=b.; %let rc=%sysfunc(grdsvc_enable(_all_, resource=SASAppGrid)); options autosignon; %put check3 &=a.; %put check3 &=b.; %syslput a=&a/REMOTE=task1; %syslput b=&b/REMOTE=task2; %syslput _USER_/REMOTE=task1; /* pass user macro variables to remote session */ %syslput _USER_/REMOTE=task2; /* pass user macro variables to remote session */ %put check4 &=a.; %put check4 &=b.; rsubmit task1; %put check5 &=a.; %put check5 &=b.; data _null_; format c $15.; c=catx(' task',"&a.",1); call symputx("c",c); run; %nrstr(%sysrput c=&c); %put check6 &=a.; %put check6 &=b.; /* start of nested parallel proc */ %let rc=%sysfunc(grdsvc_enable(_all_, resource=SASAppGrid)); options autosignon; %put check7 &=a.; %put check7 &=b.; rsubmit task2; %put check8 &=a.; %put check8 &=b.; data _null_; format d $15.; d=catx(' task',"&b.",1); call symputx("d",d); run; %nrstr(%sysrput d=&d); %put check9 &=a.; %put check9 &=b.; endrsubmit; waitfor _all_ task2; signoff task2; %put check10 &=a.; %put check10 &=b.; endrsubmit; waitfor _all_ task1; signoff task1; %put check11 &=a.; %put check11 &=b.; %put check11 &=c.; %put check11 &=d.; %mend run_outline; %run_outline();
问题根源
- 宏变量传递路径错误:外层的
%syslput b=&b/REMOTE=task2是在本地SAS会话执行的指令,但嵌套的task2会话运行在task1的远程会话内部,本地的%syslput无法直接穿透到嵌套的远程会话。 - 会话隔离性:每个RSUBMIT对应独立的SAS会话,嵌套的
task2只能直接获取其父会话(task1)的宏变量,无法直接读取本地会话的变量。 %sysrput解析问题:原代码中用%nrstr包裹%sysrput会导致宏变量无法正确解析,无法将远程生成的变量传回上层会话。
修正方案
- 调整变量传递位置:在
task1的RSUBMIT内部,用%syslput将B从task1会话传递到task2会话。 - 修正
%sysrput写法:去掉%nrstr,确保远程生成的宏变量能正确传回上层会话;若需延迟解析,可使用%bquote替代。 - 优化资源启用逻辑:嵌套会话中无需重复启用所有资源,针对当前会话处理即可。
修正后的代码
options mprint mlogic symbolgen; %let a = 1; %let b = 2; %put check1 &=a.; %put check1 &=b.; %macro run_outline(); %put check2 &=a.; %put check2 &=b.; %let rc=%sysfunc(grdsvc_enable(_all_, resource=SASAppGrid)); options autosignon; %put check3 &=a.; %put check3 &=b.; %syslput a=&a/REMOTE=task1; /* 移除本地传递B到task2的指令,改到task1内部处理 */ %syslput _USER_/REMOTE=task1; %put check4 &=a.; %put check4 &=b.; rsubmit task1; %put check5 &=a.; %put check5 &=b.; /* 从task1会话传递B到task2会话 */ %syslput b=&b/REMOTE=task2; %syslput _USER_/REMOTE=task2; data _null_; format c $15.; c=catx(' task',"&a.",1); call symputx("c",c); run; /* 修正%sysrput写法,直接传回变量到本地会话 */ %sysrput c=&c; %put check6 &=a.; %put check6 &=b.; /* start of nested parallel proc */ %let rc=%sysfunc(grdsvc_enable(task2, resource=SASAppGrid)); options autosignon; %put check7 &=a.; %put check7 &=b.; rsubmit task2; %put check8 &=a.; %put check8 &=b.; data _null_; format d $15.; d=catx(' task',"&b.",1); call symputx("d",d); run; /* 修正%sysrput,先传回task1会话,再从task1传回本地 */ %sysrput d=&d/REMOTE=task1; %put check9 &=a.; %put check9 &=b.; endrsubmit; waitfor _all_ task2; signoff task2; /* 从task1会话将d传回本地 */ %sysrput d=&d; %put check10 &=a.; %put check10 &=b.; endrsubmit; waitfor _all_ task1; signoff task1; %put check11 &=a.; %put check11 &=b.; %put check11 &=c.; %put check11 &=d.; %mend run_outline; %run_outline();
内容的提问来源于stack exchange,提问作者wellhello
相关产品推荐
相关产品推荐

