Отладка Perl с использованием флагов

Поэтому моя цель - найти простой способ включить операторы печати в Perl и установить флаг. В C/C++ вы можете использовать #define, чтобы выбрать, будет ли выполняться определенный код, и это способ включать и выключать отладочные операторы печати. Где, если определен #define DEBUG, вы что-то печатаете, иначе вы запускаете это без операторов print. Мне было интересно, есть ли простой способ сделать это в Perl.

Вот пример того, как это будет работать:

for($i = 0 ; $i < 10; $i++){
    if(debug flag){
         print some info;
    }
    do operational stuff.
}

Теперь из командной строки вы можете сделать одну из двух вещей:

1. Выполнить без отладочных операторов печати

perlScript.pl 

2. Запустите отладочные операторы печати.

perlScript.pl -debug

Или, если у кого-то есть идея получше, пожалуйста, дайте мне знать!

5 ответов

Решение

В Perl время компиляции также является временем выполнения. Так что на самом деле нет большого преимущества в использовании #define Тип заявления.

Мой обычный трюк:

my $debug = 0; 
$debug += scalar grep ( "-d", @ARGV ); 

(GetOpt это, честно говоря, лучший план, хотя)

А затем используйте:

print if $debug;
print $statement if $debug > 2;

Это означает, что у меня есть простой способ установить многословие, а также позволить мне быть избирательным в отношении этого, увеличивая утверждения.

Иногда я встраиваю обработчик сигнала, чтобы также настроить уровень отладки -

#!/usr/bin/perl

use strict;
use warnings;

my $debug = 0; 
$debug += scalar grep ( "-d", @ARGV ); 

$SIG{'USR1'} = { $debug++ };
$SIG{'USR2'} = { $debug-- };

while ( 1 ) {
    print "Debugging at: $debug\n";
    sleep 1;
}

Это больше вопрос о том, какой код я пишу - этот последний мне особенно нравится, когда я делаю forkУ меня есть все, потому что тогда я могу настраивать уровни отладки в каждой вилке независимо и на лету.

-s Опция позволяет указать значение main переменные пакета в командной строке, хотя вы должны запускать Perl-программу из файла, а не использовать -e вариант

Если у вас есть Perl-программа

use strict;
use warnings;

our $debug
print $debug, "\n";

и запустить его с помощью командной строки

perl -s myprog.pl -debug

тогда программа напечатает 1

Обратите внимание, что вместо использования -s в командной строке вы можете указать это в строке shebang в самом файле программы, так что если ваш код выглядит

#!/usr/bin/perl -s

use strict;
use warnings;

our $debug
print $debug, "\n";

тогда ваша командная строка должна содержать только

myprog.pl -debug

Я обычно использую следующий шаблон для входа в скрипты через Log:: Log4perl. Вы можете переопределить местоположения конфигурации базы журналов / журналов из командной строки (или, что более обычно, установить соответствующие местоположения по умолчанию при развертывании), и, задав один или несколько флагов -verbose для сценария, переопределить это ведение журнала и перейти на экран с помощью 4 словосочетания, дающие вам вывод на экран. Это позволяет вам легко переходить от отладки, предоставляя подробные флаги для получения каждого вывода журнала, к передаче его в пользовательскую конфигурацию обработчика журнала для отладки подсистем, к настройке ведения журнала в производственном развертывании, все с минимальными изменениями кода или без изменений.

use Getopt::Long;
use Pod::Usage;
use Log::Log4perl qw/:easy/;

my $opts = { logconf        => undef,
             logbase        => 'corp.team.app.appname'
             debug          => 0,
           };

GetOptions ( 'logconf|l=s'       => \$opts->{logconf},
             'logbase=s'         => \$opts->{logbase},
             'verbose|v+'        => \$opts->{debug},  ### debug levels - 0 = off (default), 1 = error, 2 = warn, 3 = info, 4 = debug.
                                                      ### Ignored if a logconf is provided.
           ) or pod2usage(0);

### Initialize logging subsystem
init_logger();

### Usage
logger('app_subsystem')->info('some message...');
logger()->debug('debug message...');


### Initialize logging system
sub init_logger {
    ### If a log configuration is found, and debug was not set, use it
    if (        $opts->{logconf}
         and -e $opts->{logconf}
         and  ! $opts->{debug}
       ) {
        Log::Log4perl->init($opts->{logconf});
    }
    ### Otherwise fall through to easy_init a screen logger based on the verboseness level
    ### Logging off if no config found and no verboseness set
    else {
        my ($min, $max) = ( 0, 4 );
        my %levels;
        @levels{$min .. $max} = ( $OFF, $ERROR, $WARN, $INFO, $DEBUG );
        my $log_level = $opts->{debug};
        if ($log_level < $min) {
            $log_level = $min;
        }
        elsif ($log_level > $max) {
            $log_level = $max;
        }
        Log::Log4perl->easy_init($levels{$log_level});
    }
}

### Shorthand shim sub to get a logger
### Always returns a Log::Log4perl logger object
sub logger {
    my ($category) = @_;
    if ($category) {
        return Log::Log4perl->get_logger($opts->{logbase} . '.' . $category);
    }
    return Log::Log4perl->get_logger($opts->{logbase});
}

Похоже на вашу идею, но более кратко и переходит к stderr и предполагает, что вы используете что-то вроде Getopt::Long для установки опции отладки CLI.

warn "debug info:..." if ( $debug );

До версии v5.10 вы также можете буквально использовать препроцессор C в вашем скрипте Perl с -P переключатель командной строки, задокументированный в perlrun,

#!perl -P
# myScript.pl
#define DEBUG(x) x
$foo = 42;
DEBUG( print "foo is $foo\n"; )

$ perl -P myScript.pl
foo is 42

(Словно -T переключатель, #!perl -P не использует автоматически препроцессор C с вашим скриптом, но вынуждает вас явно использовать -P переключайся каждый раз при запуске скрипта)

Другие вопросы по тегам