2012-02-24 9 views
8

W niektórych moich funkcjach chcę zamienić niektóre ostrzeżenia na błędy. Na przykład, jeśli chcę rzucać błąd podczas str2func daje MATLAB:str2func:invalidFunctionName ostrzeżenie, chciałbym wykonać następujące czynności:Konwersja ostrzeżeń na błędy w 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 

Działa to dobrze, jeśli wiem, że dany fragment kodu może dać niewielki zestaw ostrzeżeń. Jest to jednak pełne i prawdopodobnie nie skaluje się do większych bloków kodu. Czy jest lepszy sposób na zrobienie tego? Idealnie chciałbym funkcji, która może włączyć pewne ostrzeżenia do błędów w całym bloku. To pozwala mi zmienić moje przykład do:

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

Według tego wątku - http://www.mathworks.com/matlabcentral/newsreader/view_thread/158768 - na swój sposób jest tylko jeden. –

Odpowiedz

1

nie jestem świadomy czystym sposób dokładnie, co chcesz zrobić. W zależności od przyczyny dla chcących włączyć błędów do ostrzeżeń, może być w stanie dostać się z:

dbstop if warning 

lub

dbstop if warning MyFunc:InvalidFunctionName 

Można również spojrzeć na warning on stacktrace, aby uzyskać więcej infomrat6ion na ostrzeżenia jak pojawiają się.

Jeśli potrzebujesz rzeczywistego komunikatu o błędzie (a nie tylko sposób włamania się do debuggera), jestem pod wrażeniem metody, którą podałeś w pytaniu.

0

Znalazłem sposób uogólnić to nieco. Działa to w następujący sposób (podobną do tic i toc):

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

Pomiędzy setwarnings2errors i getwarnings2errors, wszystkie ostrzeżenia zawarte wygeneruje błąd, jeśli są one wyrzucane ostatnie ostrzeżenie. Dlatego nie należy go używać w dużych blokach, w których może wystąpić wiele różnych ostrzeżeń. I wdrożone z funkcji w następujący sposób:

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

Inną metodą byłoby przeciążać się ostrzeżenie. Zobacz implementację ostrzeżeń.m i warning2error.m poniżej. Największy efekt uboczny, jaki widzę z tego, to to, że na stosie pojawi się dodatkowe "ostrzeżenie.m" dla wszystkich komunikatów ostrzegawczych. Nie jestem pewien, czy jest jakikolwiek sposób obejścia tego. Musiałbyś również wyłączyć ostrzeżenie MATLAB: dispatcher: nameConflict, ponieważ przeciążamy wbudowane.

EDIT: Właśnie zauważyłem na matlabcentral.com nieudokumentowana korzystanie z wbudowanego ostrzeżeniem, że realizuje to: http://www.mathworks.com/matlabcentral/newsreader/view_thread/158768 http://undocumentedmatlab.com/blog/trapping-warnings-efficiently/

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

WYKORZYSTANIA z wiersza poleceń

warning2error ("add "," MATLAB: str2func: invalidFunctionName ")

Ostrzeżenie.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 
Powiązane problemy