【问题标题】:sequential try catch end block for matlabmatlab的顺序try catch结束块
【发布时间】:2017-09-14 15:24:54
【问题描述】:

我想运行几行代码,但我不确定是否有任何行会引发错误。但是,如果发生错误,我希望脚本忽略该行并继续。

一种选择是使用try-catch-end 块,它会跳过可能引发错误的代码块。但是,一旦发生错误,try-statement 中错误之后的其余代码都不会执行。

TL;TR:除了为以下示例代码中的每一行编写一个 try-catch-end 块之外,我还有其他选择吗?

示例代码:

try
  disp('1st line');
  disp('2nd line');
  PRODUCE_ERROR;  %throws an error, variable/function does not exist
  disp('3rd line'); %%%%%
  disp('4th line'); % these lines I would like to keep executing
  disp('5th line'); %%%%%
catch
  disp('something unexpected happened');
end

输出:

1st line
2nd line
something unexpected happened

首选输出:

1st line
2nd line
something unexpected happened
3rd line
4th line
5th line

相关:Why should I not wrap every block in "try"-"catch"?

【问题讨论】:

  • 我可以想到递归的方法来解决这个问题,但这可能不是最优雅的方法......
  • 您可以通过不重新抛出错误来继续执行其余代码。可以发minimal reproducible example吗?
  • 即使不重新抛出错误,catch 分支的其余部分也会被跳过。参见例如clear, a = 1; c = 3; try, disp(a), disp(b), disp(c), end
  • @beaker: 更新代码
  • @LuisMendo 是的,您仍然需要遍历 try/catch 块。

标签: matlab try-catch


【解决方案1】:

一种选择是将每一段代码放在一个函数中,然后遍历function handles 中的cell array。这是一个包含anonymous functions 列表的示例:

fcnList = {@() disp('1'); ...
           @() disp('2'); ...
           @() error(); ...    % Third function throws an error
           @() disp('4')};

for fcnIndex = 1:numel(fcnList)
  try
    fcnList{fcnIndex}();  % Evaluate each function
  catch
    fprintf('Error with function %d.\n', fcnIndex);  % Display when an error happens
  end
end

这是它生成的输出,表明即使在抛出错误后,函数仍会被评估:

1
2
Error with function 3.
4

上面的示例适用于以下情况:您有单行要按顺序评估的代码,但您不能将多行放入匿名函数中。在这种情况下,如果他们必须访问较大工作区中的变量,我会选择nested functions,如果他们可以独立操作,我会选择local functions。下面是一个嵌套函数的例子:

function fcn1
  b = a+1;     % Increments a
  fprintf('%d\n', b);
end
function fcn2
  error();     % Errors
end
function fcn3
  b = a.^2;    % Squares a
  fprintf('%d\n', b);
end

a = 2;
fcnList = {@fcn1 @fcn2 @fcn3};

for fcnIndex = 1:numel(fcnList)
  try
    fcnList{fcnIndex}();
  catch
    fprintf('Error with function %d.\n', fcnIndex);
  end
end

还有输出:

3
Error with function 2.
4

【讨论】:

  • 您有没有一种快速而肮脏的方法可以将代码行转换为匿名函数列表?
  • @user2305193:我添加了另一个示例。希望对您有所帮助。
  • 我的意思更简单,比如搜索和替换这些代码行。但我想这更像是一个简单的记事本替换命令(至少在 Windows 中)。多行代码的示例对我来说没有意义,因为(据我所知)围绕每个命令行编写 try-catch-end 语句需要大约等量的代码。
【解决方案2】:

一种更简单的方法是逐行读取脚本文件并依次评估每一行。这假定您要运行的脚本不包含任何多行语句(例​​如,forend 在不同的行上,或者使用... 分成多行的语句)。这是一个很大的限制,因为它是常见的,例如使用多行文本初始化矩阵。

这是函数:

function execute_script(fname)
fid = fopen(fname,'rt');
n = 0;
while ~feof(fid)
   cmd = fgetl(fid);
   n = n+1;
   if ~isempty(cmd)
      try
         evalin('caller',cmd);
      catch exception
         disp(['Error occurred executing line number ',num2str(n),': ',exception.message]);
      end
   end
end

它和我上面描述的完全一样:它读入一行,然后使用evalin 来评估调用者工作区中的那一行。创建的任何变量都是在调用者的工作区中创建的。使用的任何变量都取自调用者的工作区。

例如,我创建文件testscript.m,内容如下:

A = 1;
B = 2+C; % This line needs a variable not defined in the script!
D = 5;

接下来,在 MATLAB 命令提示符处:

>> execute_script('testscript.m')
Error occurred executing line number 2: Undefined function or variable 'C'.
>> whos
  Name      Size            Bytes  Class         Attributes

  A         1x1                 8  double                  
  D         1x1                 8  double                  

变量AD 已创建。如果我定义C:

>> C=0;
>> execute_script('testscript.m')
>> whos
  Name      Size            Bytes  Class         Attributes

  A         1x1                 8  double                  
  B         1x1                 8  double                  
  C         1x1                 8  double                  
  D         1x1                 8  double                  

定义了变量C,脚本运行时不会出错,并且还定义了B

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    相关资源
    最近更新 更多