Я работал над вилкой модуля CPAN, который теперь не поддерживается (насколько я мог рассказать). В этом модуле они используют [email protected]
для передачи сообщений об ошибках в стек. Другими словами, они устанавливают [email protected]
, если что-то пойдет не так в любом вызове подпрограмм, и они проверяют после вызова, чтобы убедиться, что он установлен. Я никогда не видел эту переменную раньше, но я думал, что это полезно, поэтому я начал использовать ее так же в коде. Теперь я недавно немного почитал об этом и обнаружил, что его назначение немного более узкое, чем это. Чтение perlvar (и другие вопросы SO по этому вопросу) не полностью отвечает за меня, но, нормально ли использовать [email protected]
таким образом? Некоторые переменные "пунктуации", которые я знаю, определенно не должны использоваться таким универсальным способом (некоторые даже с local
), является ли это одним из этих случаев, или я в порядке продолжаю эту практику?
Использование [email protected]для передачи сообщения об ошибке в модуле
Ответ 1
[email protected]
является относительно "неспешной" специальной переменной в Perl. Ничто в Perl никогда не читает от [email protected]
, и оно записывается только блоком eval {}
в конце. Это делает его относительно безопасным для использования в собственных целях сигнализации.
В частности, ядро модулей IO::Socket
модулей использует это, чтобы указать отказ от конструктора:
use IO::Socket::IP;
my $sock = IO::Socket::IP->new(...) or die "Cannot connect - [email protected]";
Более традиционный $!
здесь непригоден, потому что $!
имеет магию, которая обертывает конструкцию errno
уровня libc; это означает, что его можно установить только на целочисленное значение errno
, даже если оно может быть прочитано как число или строка. Потому что иногда могут возникать сбои, которые напрямую не связаны с значениями errno
(в случае IO::Socket
, например, для многих видов сбоев resolver), иногда $!
не подходит для этого.
Ответ 2
[email protected]
обычно не устанавливается явно. Скорее, он автоматически устанавливается для вас, когда возникает исключение. Из perldoc die
:
die LIST
die
вызывает исключение. Внутриeval
сообщение об ошибке добавляется в[email protected]
, аeval
заканчивается значением undefined. Если исключение не входит во всеeval
s, то неперехваченное исключение выводит LIST наSTDERR
и выходит с ненулевым значением. Если вам нужно выйти из процесса с помощью определенного кода выхода, см.exit
.
Например,
#!/usr/bin/perl
eval {
print "Hi\n";
die "Something went wrong here";
print "Bye\n";
};
print [email protected];
печатает
Hi
Something went wrong here at ./cr22854919 line 5.
Допустимо использовать [email protected]
для передачи сообщений об ошибках в стек таким образом, как своего рода механизм try-catch. Однако, поскольку это глобальная переменная, вы должны обработать ее как можно скорее после блока eval { }
, чтобы гарантировать, что никакой другой код не мешает вам обрабатывать исключение.
Другая магическая переменная, обычно используемая для обработки ошибок, - $!
, которая работает как errno
в C.
Пример:
my $path = "/tmp/no-such-file";
open F, '<', $path
or print STDERR "$path: $!\n";
Вывод:
/tmp/no-such-file: No such file or directory