6

假设我有一些做一些复杂工作的 some_fun。

function foo = some_complicated_fun(x,y,z,verbosity)

我已经在这段代码中写了很多调试打印,但是如果它工作正常,avg 用户可能对查看所有这些内容不感兴趣。无论如何都会打印错误语句(没有足够的参数等)。

我目前编写函数的方法是:

function foo = some_complicated_fun(x,y,z,verbosity)

(x,y,z,verbosity) = parse_args(x,y,z,verbosity); % parse args, check nargin, etc

for i=1:5, 

    % whatever    
    % do some work with x,y,z
    % blah blah

    if verbosity 
        fprintf('Now on iteration %i\n',i); % basic print
    end

    % or, with mutiple levels:
    if verbosity == 1;
        fprintf('Now on iteration %i\n',i); % basic print
    end
    if verbosity == 2;
        fprintf('x = %f,y = %f,z=%f %i\n',x,y,z); % more information
    end

    % do more work

end

我不喜欢使用 if 语句来做这件事,因为它会使代码混乱,但我想不出任何其他方式。一个班轮更好或更坏:

if verbosity; fprintf('Iteration %i\n',i); end

更好是因为它更小,更糟糕的是因为单行代码比 3 行代码的可读性差。

我想要的是一些简单、更优雅的方式来控制冗长。

那存在吗?

4

5 回答 5

2

这就是我最终做的。

我写了一个函数(我称它为 vprintf,但有更好的名字。)

我不确定我是否想做全局变量,但这是一个想法。

function vprintf(v,l,varargin)
% VPRINTF(verbosity, verbosity_level_of_statement,sprintf_style_arguments
% 
% 
% example: 
% 
% verbosity = 1;
% vprintf(verbosity,1,'This will print if verbosity is at least 1\n Verbosity = %i\n',verbosity);

if nargin<3
    error('not enough arguments');
end
if v>=l % if verbosity level is >= level of this statment
%     keyboard;
    fprintf(varargin{:});
end
于 2013-07-31T19:07:20.120 回答
1

我创建了一种控制日志输出详细程度的方法。它还没有完成,但是自从出现这个问题后,我将其上传到:

Matlab 文件交换处的此链接。

它通过将全局输出日志设置为所需的级别来工作,并将以以下格式显示消息:

OUTPUT_LEVEL:  function_which_called_message       Your_Message.

但是,它只会输出高于您设置的输出级别的消息。默认情况下只显示 INFO 消息或更高级别的消息,因此不会显示 DEBUG 和 VERBOSE 消息。如果要查看调试消息,请设置:

Output.level(Output.DISP_DEBUG)

输出方法是:

Output.VERBOSE
Output.DEBUG
Output.INFO
Output.WARNING
Output.ERROR 

您可以通过Output.'DESIRED_LEVEL'('message',input_1,input2)sprintffprintfmatlab 格式中的操作来选择要在函数中显示的消息。即,Output.INFO('The variable value is %d',variable)。对于 WARNING 和 ERROR 消息,您还可以指定标识符,如 'PACKAGE:METHOD:ERROR_ID',通过这样做,输出将在 matlabwarningerror函数上。即Output.WARNING('MY_PACKAGE:MY_METHOD:MY_ID','Something wrong happened here!')

可用的输出电平为:

Output.level(Output.DISP_VERBOSE) % Show all messages
Output.level(Output.DISP_DEBUG) % Show debug info warning errors
Output.level(Output.DISP_INFO) % Show info warning errors
Output.level(Output.DISP_WARNING) % Show warning errors
Output.level(Output.DISP_MUTE) % Show only errors.

您还可以使用指定输出到日志文件

Output.place('file_path')

并替换日志文件(您也可以使用它来重置当前日志):

Output.place('file_path',true)

或将其重置为屏幕

Output.place(1)

以下是使用输出级别 DISP_VERBOSE 的输出示例:

>> nilmContainer = NilmFileContainer.newRun('inputFolder','sim_real/','runName','RealHouse','samplesPerFile',60*60*60);
VERBOSE: getFilesOnFolder               Found 2 files on folder 'data/sim_real/'. They are the following:
VERBOSE: getFilesOnFolder                   [1]:data/sim_real/240AM000.csv
VERBOSE: getFilesOnFolder                   [2]:data/sim_real/240AM001.csv
DEBUG:   NilmFileContainer.setRunName   Updating run name to RealHouse_Run5.
INFO:    newRun                         Reading file data/sim_real/240AM000.csv.
VERBOSE: csv_data                       Reading samples (Ignored:0,Read:216000,Remaining:2422014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_1-19:12:46-30_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:216000,Read:216000,Remaining:2206014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_2-20:12:45-30_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:432000,Read:216000,Remaining:1990014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_3-21:12:45-30_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:648000,Read:216000,Remaining:1774014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_4-22:12:45-30_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:864000,Read:216000,Remaining:1558014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_5-23:12:45-30_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:1080000,Read:216000,Remaining:1342014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_6-00:12:44-31_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:1296000,Read:216000,Remaining:1126014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_7-01:12:43-31_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:1512000,Read:216000,Remaining:910014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_8-02:12:43-31_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:1728000,Read:216000,Remaining:694014) at file: sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_9-03:12:43-31_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:1944000,Read:216000,Remaining:478014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_10-04:12:42-31_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:2160000,Read:216000,Remaining:262014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_11-05:12:41-31_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:2376000,Read:216000,Remaining:46014) at file: data/sim_real/240AM000.csv.
DEBUG:   addFiles                       Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_12-06:12:41-31_10_2012.mat'
VERBOSE: csv_data                       Reading samples (Ignored:2592000,Read:46014,Remaining:0) at file: data/sim_real/240AM000.csv.
VERBOSE: csv_data                       Reading samples (Ignored:0,Read:169986,Remaining:2799058) at file: data/sim_real/240AM001.csv.
INFO:    readFile                       Found discontinuity while changing from file 'data/sim_real/240AM000.csv' to 'data/sim_real/240AM001.csv'.

正如我所说,它不是最终版本,但你可以帮助我改进它!X)

于 2013-08-01T18:39:07.653 回答
1

定义一个要替换的函数fprintf,其中包含if语句和实际打印。并声明verbosityglobal变量,以避免每次都将其作为参数传递。

于 2013-07-31T15:24:16.647 回答
1

作为对 Frederick 和 Luis Mendo 答案的改进,您可以在函数末尾将函数定义vprintf嵌套函数。它将可以访问参数verbosity,并且您不需要全局变量。您的代码如下所示:

function foo = some_complicated_fun(x,y,z,verbosity)

[x,y,z,verbosity] = parse_args(x,y,z,verbosity); % parse args, check nargin, etc

for i=1:5, 

    % whatever    
    % do some work with x,y,z
    % blah blah

    vprintf(1,'Now on iteration %i\n',i); % basic print

    % or, with mutiple levels:
    vprintf(1,'Now on iteration %i\n',i); % basic print
    vprintf(2,'x = %f,y = %f,z=%f %i\n',x,y,z); % more information

    % do more work
end

    % time to define vprintf
    function vprintf(l,varargin)
    % VPRINTF(verbosity, verbosity_level_of_statement,sprintf_style_arguments
    % 
    % 
    % example: 
    % 
    % verbosity = 1;
    % vprintf(1,'This will print if verbosity is at least 1\n Verbosity = %i\n',verbosity);

    if nargin<2
        error('not enough arguments');
    end
    if verbosity>=l % if verbosity level is >= level of this statment
    %     keyboard;
        fprintf(varargin{:});
    end
end

编辑 为了克服Gunther Struyf 在评论中提到的可维护性问题,您可以将verbosity值保留在持久变量中vprintf并在第一次调用中设置它。

function vprintf(vl,varargin)
% VPRINTF(verbosity);
% VPRINTF(verbosity_level_of_statement,sprintf_style_arguments);

persistent verbosity
if nargin==1
    verbosity = vl;
elseif isempty(verbosity)
    error('verbosity level not set');
end

if verbosity>=vl % if verbosity level is >= level of this statment
%     keyboard;
    fprintf(varargin{:});
end

然后在foo函数的开头设置它并在后面的语句中使用它。清除退出中的价值可能是一个好习惯vprintf([]);

function foo = some_complicated_fun(x,y,z,verbosity)

[x,y,z,verbosity] = parse_args(x,y,z,verbosity); % parse args, check nargin, etc

vprintf(verbosity);
for i=1:5, 

    % whatever    
    % do some work with x,y,z
    % blah blah

    vprintf(1,'Now on iteration %i\n',i); % basic print

    % or, with mutiple levels:
    vprintf(1,'Now on iteration %i\n',i); % basic print
    vprintf(2,'x = %f,y = %f,z=%f %i\n',x,y,z); % more information

    % do more work
end
vprintf([]);
于 2013-07-31T19:38:12.397 回答
0

如果我想这样做,我会创建一个 Logger 类,与logDebug类似,具有logInfologWarning和等功能logError。(我实际上在这里为 lua 做了这个

您必须在创建时设置日志级别,并且可以在 Logger 对象的范围内访问完整的功能和功能(因此没有全局范围污染并且在多个 m 文件中易于实现)。

所以这个类的最终使用看起来像这样:

%% my fancy script
% init
logger = Logger(Logger.LOGDEBUG)
logger.logDebug('script initialized');

% plot some stuff
logger.logDebug('commencing plot');
plot(rand(4));
logger.logInfo('fancy script ended');
于 2013-07-31T19:47:17.207 回答