从 Perl 中的 carp 模块覆盖 croak cluck confess carp
Overriding croak cluck confess carp from carp module in Perl
我知道如何覆盖 perl
中的内置函数并且我已经覆盖了 die
warn
say
并且因为 print
和 printf
无法覆盖我已将其绑定到我的日志记录框架的句柄。
覆盖示例 warn
:
BEGIN{ *CORE::GLOBAL::warn = sub {
my ($package, $filename, $line, $subroutine) = caller;
untie *STDERR;
my $message;
foreach my $arg (@_) {
$message = $message.$arg;
}
print STDERR $message;
tie *STDERR, __PACKAGE__, (*STDERR);
logmessage("warn",$message,$filename, $line);
return;
}
}
现在有什么方法可以覆盖 Perl
中 carp
模块的 croak cluck confess carp
吗?
Carp 提供的函数只是常规函数,当模块为 use
d 时,它们通过 Exporter 导入到您的包中。诀窍是在任何人导入它们之前,尽早在 Carp
命名空间 中覆盖它们 。然后当他们这样做时,他们会得到被覆盖的。
在您的脚本中,或在您自己的日志记录模块的最顶部:
BEGIN {
require Carp;
# save original croak (will create closure ...)
my $original_croak = \&Carp::croak;
no warnings 'redefine';
*Carp::croak = sub {
print "Croaking...\n"
or $original_croak->("cannot fake croak"); # (... here)
};
}
您需要加载 Carp 一次,以便 Perl 解析代码并将函数安装在 Carp
命名空间中。然后你可以覆盖它们。
稍后,在您代码的其他模块中:
use Carp 'croak';
croak 'foo';
这将产生我们上面设置的输出。
如果您想在新的 Carp::croak
中调用原始的 Carp::croak
,请将其保存到 coderef 并保留它,如上例所示。
请注意,这仅在替换发生得非常早时才有效。如果你把它放在你自己的日志模块中,并且它在 Carp 加载后加载,这将失败。
package Foo;
use Carp;
use Your::Logging::Framework;
croak 'foo';
将不起作用,因为在您覆盖 Carp::croak
的位置,Foo::croak
已经是原始 Carp::croak
.
的副本
如果你想让它工作,你总是可以将你自己的 carp
、croak
等等显式地导入调用者。这会在 strict
下引发一堆警告或抱怨,但它应该有效。
我知道如何覆盖 perl
中的内置函数并且我已经覆盖了 die
warn
say
并且因为 print
和 printf
无法覆盖我已将其绑定到我的日志记录框架的句柄。
覆盖示例 warn
:
BEGIN{ *CORE::GLOBAL::warn = sub {
my ($package, $filename, $line, $subroutine) = caller;
untie *STDERR;
my $message;
foreach my $arg (@_) {
$message = $message.$arg;
}
print STDERR $message;
tie *STDERR, __PACKAGE__, (*STDERR);
logmessage("warn",$message,$filename, $line);
return;
}
}
现在有什么方法可以覆盖 Perl
中 carp
模块的 croak cluck confess carp
吗?
Carp 提供的函数只是常规函数,当模块为 use
d 时,它们通过 Exporter 导入到您的包中。诀窍是在任何人导入它们之前,尽早在 Carp
命名空间 中覆盖它们 。然后当他们这样做时,他们会得到被覆盖的。
在您的脚本中,或在您自己的日志记录模块的最顶部:
BEGIN {
require Carp;
# save original croak (will create closure ...)
my $original_croak = \&Carp::croak;
no warnings 'redefine';
*Carp::croak = sub {
print "Croaking...\n"
or $original_croak->("cannot fake croak"); # (... here)
};
}
您需要加载 Carp 一次,以便 Perl 解析代码并将函数安装在 Carp
命名空间中。然后你可以覆盖它们。
稍后,在您代码的其他模块中:
use Carp 'croak';
croak 'foo';
这将产生我们上面设置的输出。
如果您想在新的 Carp::croak
中调用原始的 Carp::croak
,请将其保存到 coderef 并保留它,如上例所示。
请注意,这仅在替换发生得非常早时才有效。如果你把它放在你自己的日志模块中,并且它在 Carp 加载后加载,这将失败。
package Foo;
use Carp;
use Your::Logging::Framework;
croak 'foo';
将不起作用,因为在您覆盖 Carp::croak
的位置,Foo::croak
已经是原始 Carp::croak
.
如果你想让它工作,你总是可以将你自己的 carp
、croak
等等显式地导入调用者。这会在 strict
下引发一堆警告或抱怨,但它应该有效。