Carp
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- СИНОПСИС
- ОПИСАНИЕ
- ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
- ОШИБКИ
- СМОТРИТЕ ТАКЖЕ
- СОТРУДНИЧЕСТВО
- АВТОР
- АВТОРСКИЕ ПРАВА
- ЛИЦЕНЗИЯ
НАЗВАНИЕ
Carp - альтернативные warn и die для модулей
СИНОПСИС
use Carp;
# warn user (from perspective of caller)
carp "string trimmed to 80 chars";
# die of errors (from perspective of caller)
croak "We're outta here!";
# die of errors with stack backtrace
confess "not implemented";
# cluck, longmess and shortmess not exported by default
use Carp qw(cluck longmess shortmess);
cluck "This is how we got here!"; # warn with stack backtrace
$long_message = longmess( "message from cluck() or confess()" );
$short_message = shortmess( "message from carp() or croak()" ); ОПИСАНИЕ
Процедуры Carp полезны в собственных модулях, так как они ведут себя как die() или warn(), но с сообщением, которое, скорее всего, будет полезно пользователю вашего модуля. В случае cluck() и confess(), этот контекст представляет собой сводку каждого вызова в стеке вызовов; longmess() возвращает содержимое сообщения об ошибке.
Для более короткого сообщения можно использовать carp() или croak(), которые сообщают об ошибке как о произошедшей там, где ваш модуль был вызван. shortmess() возвращает содержимое этого сообщения об ошибке. Нет гарантии, что ошибка произошла именно там, но это разумное предположение.
Carp позаботится о том, чтобы не перезаписывать переменные состояния $! и $^E в процессе формирования сообщений об ошибках. Это означает, что обработчик $SIG{__DIE__} или $SIG{__WARN__} может получить информацию об ошибке, хранящуюся в этих переменных, если требуется дополнить сообщение об ошибке, и если код, вызывающий Carp, оставил там полезные значения. Конечно, Carp не может гарантировать последнее.
Также можно изменить способ работы вывода и логики Carp, изменив некоторые глобальные переменные в пространстве имен Carp. См. раздел GLOBAL VARIABLES ниже.
Вот более подробное описание работы carp и croak. Они ищут в стеке вызовов вызов функции, для которого не было указано, что не должно быть ошибки. Если все вызовы отмечены как безопасные, они отказываются и возвращают полный стек вызовов вместо этого. Другими словами, они предполагают, что первый потенциально подозрительный вызов является виновником. Их правила определения того, что вызов не должен генерировать ошибки, работают следующим образом:
-
Любой вызов из пакета в сам себя безопасен.
-
Пакеты утверждают, что при вызовах в или из пакетов, явно отмеченных как безопасные включением в
@CARP_NOT, или (если этот массив пуст)@ISA, не будет ошибок. Возможность переопределения того, что говорит @ISA, является новой в 5.8. -
Доверие в пункте 2 является транзитивным. Если А доверяет В, а В доверяет С, то А доверяет С. Поэтому, если вы не переопределите
@ISAс@CARP_NOT, это отношение доверия идентично «унаследованному». -
Любой вызов из внутреннего модуля Perl безопасен. (Ничто не мешает пользовательским модулям отмечать себя как внутренние для Perl, но такая практика не рекомендуется.)
-
Любой вызов системы предупреждений Perl (например, Carp сам по себе) безопасен. (Это правило не позволяет ему сообщать об ошибке в точке вызова
carpилиcroak.) -
$Carp::CarpLevelможет быть установлен для пропуска определенного количества дополнительных уровней вызовов. Использование этого не рекомендуется, так как очень сложно добиться правильного поведения.
Вынужденный вывод стека вызовов
В качестве средства отладки можно принудить Carp обрабатывать croak как confess, а carp как cluck во всех модулях. Другими словами, принудительно вывести подробный стек вызовов. Это может быть очень полезно при попытке понять, почему или откуда генерируется предупреждение или ошибка.
Эта функция включена путем «импорта» несуществующего символа «verbose». Обычно это делается так:
perl -MCarp=verbose script.pl или путем включения строки -MCarp=verbose в переменной среды PERL5OPT.
Альтернативно можно установить глобальную переменную $Carp::Verbose в значение true. См. раздел GLOBAL VARIABLES ниже.
Форматирование стека вызовов
На каждом уровне стека отображается имя подпрограммы вместе с её параметрами. Для простых скаляров этого достаточно. Для сложных типов данных, таких как объекты и другие ссылки, это может просто отобразить 'HASH(0x1ab36d8)'.
Carp предоставляет два способа управления этим.
-
Для объектов будет вызван метод
CARP_TRACE, если он существует. Если этот метод не существует, или он рекурсивно вызываетCarp, или по какой-либо другой причине генерирует исключение, это пропускается, и Carp переходит к следующему варианту, в противном случае проверка останавливается, и возвращенная строка используется. Рекомендуется, чтобы тип объекта был частью строки для более удобной отладки. -
Для любого типа ссылки проверяется
$Carp::RefArgFormatter. Эта переменная должна быть ссылкой на код, и в неё передаётся текущий параметр. Если эта функция не существует (переменная undef), или она рекурсивно вызываетCarp, или по какой-либо другой причине генерирует исключение, это пропускается, и Carp переходит к следующему варианту, в противном случае проверка останавливается, и возвращенная строка используется. -
В противном случае, если ни
CARP_TRACE, ни$Carp::RefArgFormatterнедоступны, значение преобразуется в строку, игнорируя любые перегрузки.
ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
$Carp::MaxEvalLen
Эта переменная определяет количество символов строки-eval, отображаемых в выводе. Используйте значение 0 для отображения всего текста.
По умолчанию 0.
$Carp::MaxArgLen
Эта переменная определяет количество символов каждого аргумента функции, которые нужно отобразить. Используйте значение 0 для отображения всей длины аргумента.
По умолчанию 64.
$Carp::MaxArgNums
Эта переменная определяет количество аргументов каждой функции, которые нужно отобразить. Используйте ложное значение, чтобы отобразить все аргументы вызова функции. Для подавления всех аргументов используйте -1 или '0 but true'.
По умолчанию 8.
$Carp::Verbose
Эта переменная заставляет carp() и croak() генерировать стеки вызовов, как и cluck() и confess(). Так реализован use Carp 'verbose' внутри.
По умолчанию 0.
$Carp::RefArgFormatter
Эта переменная устанавливает общий формат отображения ссылок. Простые скаляры и объекты, реализующие CARP_TRACE, не будут проходить через этот форматтер. Вызов Carp изнутри этой функции не поддерживается.
local $Carp::RefArgFormatter = sub { require Data::Dumper; Data::Dumper::Dump($_[0]); # не обязательно безопасно };
@CARP_NOT
Эта переменная (в вашем пакете) указывает, какие пакеты не следует учитывать как местоположение ошибки. Функции carp() и cluck() пропустят вызывающие стороны при указании места возникновения ошибки.
ПРИМЕЧАНИЕ: Эта переменная должна находиться в таблице символов пакета, таким образом:
# These work
our @CARP_NOT; # file scope
use vars qw(@CARP_NOT); # package scope
@My::Package::CARP_NOT = ... ; # explicit package variable
# These don't work
sub xyz { ... @CARP_NOT = ... } # w/o declarations above
my @CARP_NOT; # even at top-level Пример использования:
package My::Carping::Package;
use Carp;
our @CARP_NOT;
sub bar { .... or _error('Wrong input') }
sub _error {
# temporary control of where'ness, __PACKAGE__ is implicit
local @CARP_NOT = qw(My::Friendly::Caller);
carp(@_)
} Это заставит Carp сообщать об ошибке как о произошедшей из вызывающей стороны, не находящейся ни в My::Carping::Package, ни в My::Friendly::Caller.
Также прочтите раздел "ОПИСАНИЕ" выше, о том, как Carp определяет, откуда сообщать об ошибке.
Используйте @CARP_NOT, а не $Carp::CarpLevel.
Переопределяет использование Carp @ISA.
%Carp::Internal
Это указывает, какие пакеты являются внутренними для Perl. Carp никогда не будет сообщать об ошибке как о произошедшей на строке в пакете, который является внутренним для Perl. Например:
$Carp::Internal{ (__PACKAGE__) }++;
# time passes...
sub foo { ... or confess("whatever") }; позволит получить полный стек вызовов, начиная с первого вызывающего модуля за пределами __PACKAGE__. (Если этот пакет также является внутренним для Perl.)
%Carp::CarpInternal
Это указывает, какие пакеты являются внутренними для системы предупреждений Perl. Для генерации полного стека вызовов это эквивалентно тому, что пакет является внутренним для Perl: стек вызовов не начнётся внутри пакетов, перечисленных в %Carp::CarpInternal. Но это немного отличается для сводного сообщения, генерируемого carp или croak. В этих случаях ошибки не будут отображаться на строках, вызывающих пакеты из %Carp::CarpInternal.
Например, Carp сам по себе находится в %Carp::CarpInternal. Поэтому полный стек вызовов из confess не начнётся внутри Carp, а короткое сообщение от вызова croak не будет размещено на строке, где был вызван croak.
$Carp::CarpLevel
Эта переменная определяет количество дополнительных кадров вызовов, которые необходимо пропустить при указании места возникновения ошибки при вызове одной из функций Carp. Подсчитать эти кадры при вызовах, генерирующих полный стек вызовов, довольно легко. Однако гораздо сложнее учесть вызовы, генерирующие короткое сообщение. Обычно люди пропускают слишком много кадров вызовов. Если им повезёт, они пропустят достаточно, чтобы Carp пройдёт весь стек вызовов, поймет, что что-то не так, и затем сгенерирует полный стек вызовов. Если им не повезёт, ошибка будет сообщаться с вводящего в заблуждение места очень высоко в стеке вызовов.
Поэтому лучше избегать $Carp::CarpLevel. Вместо этого используйте @CARP_NOT, %Carp::Internal и %Carp::CarpInternal.
По умолчанию 0.
ОШИБКИ
В настоящее время процедуры Carp не обрабатывают объекты исключений. Если они вызываются с первым аргументом, являющимся ссылкой, они просто вызывают die() или warn(), в зависимости от ситуации.
СМОТРИТЕ ТАКЖЕ
СОТРУДНИЧЕСТВО
Carp поддерживается разработчиками perl 5 в рамках репозитория контроля версий ядра perl 5. Пожалуйста, обратитесь к perlhack perldoc, чтобы узнать, как отправлять исправления и участвовать в разработке.
АВТОР
Модуль Carp впервые появился в дистрибутиве perl 5.000 Ларри Уолла. С тех пор его модифицировали несколько разработчиков perl 5. Эндрю Мэйн (Zefram) <zefram@fysh.org> выделил Carp в самостоятельный дистрибутив.
АВТОРСКИЕ ПРАВА
Авторские права (C) 1994-2013 Ларри Уолл
Авторские права (C) 2011, 2012, 2013 Эндрю Мэйн (Zefram) <zefram@fysh.org>
ЛИЦЕНЗИЯ
Этот модуль является свободным программным обеспечением; вы можете распространять и/или изменять его на тех же условиях, что и Perl сам по себе.
© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.28.3/Carp