我有一组日志和调试功能,我想在多个模块/对象中使用它们.我希望能够使用命令行开关全局打开/关闭它们.
下面的代码执行此操作,但是,我希望能够省略包名并将所有内容保存在单个文件中.
更具体地说,我想将日志记录函数名称导入到每个模块中,以便可以在没有任何包名称限定的情况下调用它们(类似于C++ use namespace;指令),并且我希望能够从使用的脚本全局启用/禁用它们它们在我下面的示例代码中.
另一件事 - 我不认为我完全理解为什么以下代码有效.
#! /usr/bin/perl -w
use strict;
use Getopt::Long;
{
package LogFuncs;
use threads;
use Time::HiRes qw( gettimeofday );
# provide tcpdump style time stamp
sub _gf_time {
my ( $seconds, $microseconds ) = gettimeofday();
my @time = localtime($seconds);
return sprintf( "%02d:%02d:%02d.%06ld",
$time[2], $time[1], $time[0], $microseconds );
}
sub logerr;
sub compile {
my %params = @_;
*logerr = $params{do_logging}
? sub {
my $msg = shift;
warn _gf_time() . " Thread " . threads->tid() . ": $msg\n";
}
: sub { };
}
}
{
package FooObj;
sub new {
my $class = shift;
bless {}, $class;
};
sub foo_work {
my $self = shift;
# do some foo work
LogFuncs::logerr($self);
}
}
{
package BarObj;
sub new {
my $class = shift;
my $data = { fooObj => FooObj->new() };
bless $data, $class;
}
sub bar_work {
my $self = shift;
$self->{fooObj}->foo_work();
LogFuncs::logerr($self);
}
}
my $do_logging = 0;
GetOptions(
"do_logging" => \$do_logging,
);
LogFuncs::compile(do_logging => $do_logging);
my $bar = BarObj->new();
LogFuncs::logerr("Created $bar");
$bar->bar_work();
Run Code Online (Sandbox Code Playgroud)
如果您想将所有内容保存在同一个文件中,为什么不将记录器放在文件范围词汇的顶部.
GetOptions( do_logging => \$do_logging );
my $logerr = $do_logging ? sub {logging_code_here()} : sub {};
Run Code Online (Sandbox Code Playgroud)
$logerr 现在可以在同一文件中该点之后定义的任何包中使用.
但是,构建日志记录调用通常更快,如下所示:
my $logerr = sub { logging_code_here() };
$logerr->("some string $some_var") if $do_logging;
Run Code Online (Sandbox Code Playgroud)
这样你就可以避免子程序调用,如果日志记录关闭,则不需要计算$ logerr的字符串参数.
您还可以设置日志记录级别:
$logerr->("starting loop") if $do_logging;
for (@big_array) {
$logerr->("processing $_") if $do_logging > 1;
...
}
Run Code Online (Sandbox Code Playgroud)
编辑:虽然我不认为这是最好的做法,根据你的意见,这是你可能正在寻找的(一个pragma):
use 5.010;
use warnings;
use strict;
BEGIN { # compile time
$INC{'log.pm'}++; # block 'require log;'
package log;
sub is_active {(caller 1)[10]{log}} # test the hints hash
sub import {
$^H{log} = 1; # set the hints hash for 'log'
my $logmsg = (caller).'::logmsg'; # name of caller's sub
no strict 'refs';
*$logmsg = sub {print "logging: @_\n" if is_active} # install sub
unless *{$logmsg}{CODE}; # unless we did already
}
sub unimport {
$^H{log} = 0; # unset the hints hash
}
}
package MyPkg;
use log;
logmsg 'hello, world!';
{
no log;
logmsg 'nope, not here';
}
logmsg 'back again';
Run Code Online (Sandbox Code Playgroud)