Преодоление кваканья cluck confess carp из модуля Carp на 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;
        }
}

Есть ли способ переопределить croak cluck confess carp из модуля carp в Perl?


person Dinesh Gowda    schedule 09.10.2017    source источник


Ответы (1)


Функции, предоставляемые Carp, - это просто обычные функции, которые импортируются в ваши пакеты через Exporter, когда модуль имеет значение used. Уловка состоит в том, чтобы перезаписать их как можно раньше внутри 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, это не удастся.

package Foo;
use Carp;
use Your::Logging::Framework;

croak 'foo';

Не будет работать, потому что на момент перезаписи Carp::croak, Foo::croak уже является копией оригинала Carp::croak.

Если вы хотите, чтобы это работало, вы всегда можете явно импортировать свои собственные carp, croak и так далее в вызывающую программу. Это вызовет кучу предупреждений или жалоб в strict, но это должно сработать.

person simbabque    schedule 09.10.2017
comment
Спасибо, так как я устанавливаю env {PERL5OPT} = -MMyLoggingModule, я должен работать. У меня есть еще один вопрос, могу ли я назвать реальное карканье внутри моего подавленного карканья? - person Dinesh Gowda; 09.10.2017
comment
@DineshGowda Я думал, что адресовал это. Похоже, я этого не делал. Вам нужно сохранить исходный, например в переменную. Я отредактирую. - person simbabque; 09.10.2017