从 Perl 中的 carp 模块覆盖 croak cluck confess carp

Overriding croak cluck confess carp from carp module in Perl

我知道如何覆盖 perl 中的内置函数并且我已经覆盖了 die warn say 并且因为 printprintf 无法覆盖我已将其绑定到我的日志记录框架的句柄。

覆盖示例 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;
        }
}

现在有什么方法可以覆盖 Perlcarp 模块的 croak cluck confess carp 吗?

Carp 提供的函数只是常规函数,当模块为 used 时,它们通过 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.

的副本

如果你想让它工作,你总是可以将你自己的 carpcroak 等等显式地导入调用者。这会在 strict 下引发一堆警告或抱怨,但它应该有效。