MATLAB中警告到错误的转换

MATLAB中警告到错误的转换,matlab,error-handling,warnings,Matlab,Error Handling,Warnings,在我的一些函数中,我想将一些警告转换为错误。例如,如果我想在str2func产生MATLAB:str2func:invalidFunctionName警告时抛出错误,我将执行以下操作: invalid_func_id = 'MATLAB:str2func:invalidFunctionName'; %hide warning of interest warning('off', invalid_func_id); %this might yield the warning of interest

在我的一些函数中,我想将一些警告转换为错误。例如,如果我想在
str2func
产生
MATLAB:str2func:invalidFunctionName
警告时抛出错误,我将执行以下操作:

invalid_func_id = 'MATLAB:str2func:invalidFunctionName';
%hide warning of interest
warning('off', invalid_func_id);
%this might yield the warning of interest
predicate_func_try = str2func(predicate_func);
[~, warn_id] = lastwarn;
assert(~strcmp(warn_id, invalid_func_id)...
    , 'MyFunc:InvalidFunctionName'...
    , 'The predicate function %s does not have a valid name'...
    , predicate_func...
    );
warning on all
如果我知道一个特定的代码块可以给出一组小的警告,那么这就很好了。但是,它非常冗长,可能无法扩展到更大的代码块。有更好的方法吗?理想情况下,我想要一个函数,它可以将某些警告转换为整个块中的错误。这将允许我将我的示例修改为:

warnings2errors('MATLAB:str2func:invalidFunctionName');
predicate_func_try = str2func(predicate_func);
warnings2errors('off');

我不知道一个干净的方法来做你想做的事。根据您希望将错误转化为警告的原因,您可以通过以下方式解决:

dbstop if warning

您还可以查看stacktrace上的
警告
,以获取有关警告出现时的更多信息


如果您需要实际的错误消息(不仅仅是一种进入调试器的方法),那么您在问题中包含的方法实际上给我留下了深刻的印象。

我找到了一种方法来概括这一点。其工作方式如下(类似于
tic
toc
):

setwarnings2errors
getwarnings2errors
之间,所有设置的警告如果是最后一次抛出的警告,都将抛出错误。因此,它不应该用于可能出现许多不同警告的大型块中。我通过以下方式实现了这些功能:

设置警告2错误:

function warning_ids = setwarnings2errors(varargin)
warning_ids = cell(nargin, 1);
for x_ = 1:nargin
    local_arg = varargin{x_};
    assert(ischar(local_arg));
    evalin('caller', sprintf('warning off %s', local_arg));
    warning_ids{x_} = local_arg;
end
end
function getwarnings2errors(warning_ids)
[lastwarn_str, lastwarn_id] = evalin('caller', 'lastwarn');
num_warns = numel(warning_ids);
try
    for x_ = 1:num_warns
        local_warn = warning_ids{x_};
        assert(~strcmp(local_warn, lastwarn_id)...
            , lastwarn_id...
            , lastwarn_str...
            );
    end
catch m_e
    evalin('caller', 'warning on all');
    throwAsCaller(m_e);
end
evalin('caller', 'warning on all');
end
GetWarnings2错误:

function warning_ids = setwarnings2errors(varargin)
warning_ids = cell(nargin, 1);
for x_ = 1:nargin
    local_arg = varargin{x_};
    assert(ischar(local_arg));
    evalin('caller', sprintf('warning off %s', local_arg));
    warning_ids{x_} = local_arg;
end
end
function getwarnings2errors(warning_ids)
[lastwarn_str, lastwarn_id] = evalin('caller', 'lastwarn');
num_warns = numel(warning_ids);
try
    for x_ = 1:num_warns
        local_warn = warning_ids{x_};
        assert(~strcmp(local_warn, lastwarn_id)...
            , lastwarn_id...
            , lastwarn_str...
            );
    end
catch m_e
    evalin('caller', 'warning on all');
    throwAsCaller(m_e);
end
evalin('caller', 'warning on all');
end

另一种方法是重载警告本身。请参阅下面warning.m和warning2error.m的实现。我从中看到的最大的副作用是,对于所有警告消息,堆栈上将显示一个额外的“warning.m”。不确定是否有办法解决这个问题。此外,您还需要禁用MATLAB:dispatcher:nameConflict警告,因为我们正在重载内置的

编辑:刚刚在matlabcentral.com上注意到一个未记录的内置警告用法,它实现了以下功能:

来自命令行的用法

警告2错误('add','MATLAB:str2func:invalidFunctionName')

警告:m:

% Overload of warning.m to enable conversion of certain warnings to errors
% via warning2error.m
%
% Will want to disable warning "MATLAB:dispatcher:nameConflict" via command
% warning('off','MATLAB:dispatcher:nameConflict');
%
% Jesse Hopkins
% Oct. 2 2012

function varargout = warning(varargin)
    %check for component:mnemonic syntax
    if nargin >= 2 && ischar(varargin{1}) && any(regexp(varargin{1},'^(\w+:\w+){1,}$','start','once'))
        %we've captured  <component>[:<component>]:<mnemonic>syntax

        %check if this is in the list
        if warning2error('query',varargin{1})
            %YES, convert to error
            ME = MException(varargin{1},varargin{2:end});
            ME = ME.addCause(MException('Warning2Error:ConvertedWarning','Converted warning "%s" to error becuase it was registered via warning2error.m.',varargin{1}));
            ME.throwAsCaller;
        end
    end

    %pass through to built-in warning
    varargout{1:nargout} = builtin('warning',varargin{:});
end
%重载warning.m以启用某些警告到错误的转换
%via warning2error.m
%
%希望通过命令禁用警告“MATLAB:dispatcher:nameConflict”
%警告('off','MATLAB:dispatcher:nameConflict');
%
%杰西·霍普金斯
%2012年10月2日
函数varargout=警告(varargin)
%检查组件:助记符语法
如果nargin>=2&&ischar(varargin{1})&&any(regexp(varargin{1}),^(\w+:\w+{1,}$,'start','once'))
%我们已捕获[:]:语法
%检查是否在列表中
if warning2error('query',varargin{1})
%是,转换为错误
ME=MException(varargin{1},varargin{2:end});
ME=ME.addCause(MException('Warning2Error:ConvertedWarning','ConvertedWarning”%s“转换为错误,因为它是通过Warning2Error.m.注册的,varargin{1}));
我是一个打电话的人;
结束
结束
%传递到内置警告
varargout{1:nargout}=builtin('warning',varargin{:});
结束
警告2错误m:

%warning2error.m
%USAGE:
%   Add warnings to convert to errors.
%  warning2error('add','<component>[:<component>]:<mnemonic>',...
%
%   Remove warnings to convert to errors
%   warning2error('remove','<component>[:<component>]:<mnemonic>',...
%
%   Query warnings to convert to errors 
%   tf = warning2error('query','<component>[:<component>]:<mnemonic>')
%
%   Get entire list of warnings converted to errors
%   list = warning2error('get')
%
% Jesse Hopkins
% Oct 2 2012

function varargout = warning2error(op,varargin)
    persistent list;
    if isempty(list)
        list = {};
    end
    varargout={};

    switch lower(op)
        case 'add'
            list = unique([list(:);varargin(:)]);
        case 'remove'
            for i = 1:length(varargin)
                [tf idx] = ismember(varargin{i},list);
                allidx = 1:length(list);
                newidx = setdiff(allidx,idx);
                list = list(newidx);
            end
        case 'clear'
            list = {};
        case 'get'
            varargout{1} = list;
        case 'query'
            out = false(1,length(varargin));
            for i = 1:length(varargin)
                out(i) = ismember(varargin{1},list);
            end
            varargout{1} = out;
    end
end
%warning2error.m
%用法:
%添加警告以转换为错误。
%警告2错误('add','[:]:',。。。
%
%删除要转换为错误的警告
%警告2错误('remove','[:]:',。。。
%
%查询要转换为错误的警告
%tf=warning2error('query','[:]:')
%
%获取转换为错误的警告的完整列表
%list=warning2error('get')
%
%杰西·霍普金斯
%2012年10月2日
函数varargout=warning2error(op,varargin)
持久性列表;
如果是空的(列表)
列表={};
结束
varargout={};
开关降下(op)
案例“添加”
list=unique([list(:);varargin(:)]);
“删除”案例
对于i=1:长度(varargin)
[tf idx]=ismember(varargin{i},list);
allidx=1:长度(列表);
newidx=setdiff(allidx,idx);
列表=列表(newidx);
结束
案例“清楚”
列表={};
案例“得到”
varargout{1}=列表;
案例“查询”
out=false(1,长度(varargin));
对于i=1:长度(varargin)
out(i)=ismember(varargin{1},list);
结束
varargout{1}=out;
结束
结束
根据这条线索——你的方式是唯一的。
%warning2error.m
%USAGE:
%   Add warnings to convert to errors.
%  warning2error('add','<component>[:<component>]:<mnemonic>',...
%
%   Remove warnings to convert to errors
%   warning2error('remove','<component>[:<component>]:<mnemonic>',...
%
%   Query warnings to convert to errors 
%   tf = warning2error('query','<component>[:<component>]:<mnemonic>')
%
%   Get entire list of warnings converted to errors
%   list = warning2error('get')
%
% Jesse Hopkins
% Oct 2 2012

function varargout = warning2error(op,varargin)
    persistent list;
    if isempty(list)
        list = {};
    end
    varargout={};

    switch lower(op)
        case 'add'
            list = unique([list(:);varargin(:)]);
        case 'remove'
            for i = 1:length(varargin)
                [tf idx] = ismember(varargin{i},list);
                allidx = 1:length(list);
                newidx = setdiff(allidx,idx);
                list = list(newidx);
            end
        case 'clear'
            list = {};
        case 'get'
            varargout{1} = list;
        case 'query'
            out = false(1,length(varargin));
            for i = 1:length(varargin)
                out(i) = ismember(varargin{1},list);
            end
            varargout{1} = out;
    end
end