Как мне перехватить и сбросить ошибку в Perl? - PullRequest
4 голосов
/ 11 мая 2011

Допустим, у меня есть модуль Bar, который является оболочкой подкласса для модуля Foo.Я хочу, чтобы вызовы методов Бар точно имитировали методы Фу - вплоть до фатальных ошибок.Пока все достаточно просто;Я просто вызываю метод SUPER.


sub stuff {
    # Do stuff here

    SUPER::stuff(@_);

    # Do more stuff here
}

Но, скажем, я хочу перехватывать, регистрировать и перебрасывать любые фатальные ошибки, которые выдает SUPER::stuff().Первые два шага просты:


sub stuff {
    # Do stuff here

    eval {
        SUPER::stuff(@_);
    };
    $@ and log("Naughty, naughty: $@");

    # Do more stuff here
}

... но я не знаю, как сделать последнюю часть.Как мне повторно выдать ошибку таким образом, что вызывающий абонент не сможет различить вызов на Foo->stuff() и вызов на Bar->stuff()?Могу ли я просто вставить die $@ после оператора log и ожидать, что он будет делать то, что я хочу, или здесь есть нюансы, которые могут вызвать у меня проблемы?

Ответы [ 3 ]

5 голосов
/ 12 мая 2011

Полный код для безопасной оценки / отлова / журнала / переброса в Perl может быть немного многословным.

sub stuff {
    # Do stuff here

    local $@; # don't reset $@ for our caller.
    my $eval_ok = eval { # get the return from eval, it will be undef if the eval catches an error.
        SUPER::stuff(@_);
        1; # return 1 (true) if there are no errors caught.
    };
    if (!$eval_ok) { # don't trust $@ it might have been reset as the eval unrolled.
        my $error = $@ || 'unknown error'; # copy $@ incase write_log resets $@, or is later changed to cause it to reset $@.
        write_log("Naughty, naughty: $error");
        die $error; # after all that we can rethrow our error.
    }

    # Do more stuff here
}

Вы можете использовать Try :: Tiny , предложенный мобом для упрощения:

sub stuff {
    # Do stuff here

    try {
        SUPER::stuff(@_);
    } catch {
        my $error = $_;
        write_log("Naughty, naughty: $error");
        die $error;
    }

    # Do more stuff here
}
1 голос
/ 11 мая 2011
 eval {
        SUPER::stuff(@_);
    };
    $@ and ( log("Naughty, naughty: $@"), die $@ );
1 голос
/ 11 мая 2011

То, что вы предлагаете, будет работать. Perl не имеет структурированных исключений, поэтому данные в $@ - это все, что может получить вызывающая программа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...