2012-02-24 18 views
8

En algunas de mis funciones quiero convertir algunas advertencias en errores. Por ejemplo, si quiero lanzar un error cuando str2func produce una advertencia MATLAB:str2func:invalidFunctionName, me gustaría hacer lo siguiente:conversión de advertencias a errores en MATLAB

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 

Esto funciona bien si sé que un bloque de código puede dar un pequeño conjunto de advertencias. Sin embargo, es detallado y probablemente no se escale a bloques de código más grandes. ¿Hay una mejor manera de hacer esto? Idealmente, me gustaría una función que pueda convertir ciertas advertencias en errores en un bloque completo. Me permitiría modificar mi ejemplo a:

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

De acuerdo con este hilo - http://www.mathworks.com/matlabcentral/newsreader/view_thread/158768 - su camino es el único. –

Respuesta

1

No conozco una manera clara de hacer exactamente lo que quiere. Dependiendo de la razón para querer transformar los errores en las advertencias, es posible que pueda pasar con:

dbstop if warning 

o

dbstop if warning MyFunc:InvalidFunctionName 

También puede mirar en warning on stacktrace, para obtener más infomrat6ion sobre las advertencias como ellos aparecen.

Si necesita un mensaje de error real (no solo una forma de entrar en el depurador) entonces estoy bastante impresionado con el método que incluyó en la pregunta.

0

Encontré una manera de generalizar esto de alguna manera. Funciona de la siguiente manera (similar a tic y toc):

warn_ids = setwarnings2errors('MATLAB:str2func:invalidFunctionName'); 
predicate_func_try = str2func(predicate_func); 
getwarnings2errors(warn_ids); 

Entre setwarnings2errors y getwarnings2errors, todas las advertencias a que se generará un error si son la última advertencia lanzada. Por lo tanto, no debe usarse en bloques grandes donde pueden ocurrir muchas advertencias diferentes. He implementado las funciones de la siguiente manera:

setwarnings2errors:

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 

getwarnings2errors:

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 
5

Otro método sería sobrecargar advertencia en sí. Ver la implementación de warning.m y warning2error.m a continuación. El mayor efecto secundario que veo de esto es que verá un "warning.m" adicional en la pila para todos los mensajes de advertencia. No estoy seguro de si hay una forma de evitar eso. Además, necesitaría deshabilitar la advertencia de MATLAB: dispatcher: nameConflict ya que estamos sobrecargando un builtin.

EDIT: acabo de dar cuenta de matlabcentral.com un uso documentado de la advertencia orden interna que logra esto: http://www.mathworks.com/matlabcentral/newsreader/view_thread/158768 http://undocumentedmatlab.com/blog/trapping-warnings-efficiently/

>> warning('error','MATLAB:str2func:invalidFunctionName') 

USO DE LÍNEA DE COMANDO

warning2error ('añadir ',' MATLAB: str2func: invalidFunctionName ')

Advertencia.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 

Warning2Error.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 
Cuestiones relacionadas