#perl #file #error-handling #stat
#perl #файл #обработка ошибок #статистика
Вопрос:
У меня возникла проблема, в которой я, кажется, не могу разобраться, и я надеюсь, что вы, ребята, сможете мне помочь.
Проблема возникает, когда :
- Я использую пользовательскую обработку ошибок
- Я использую File::Stat в отдельном модуле
Пример:
Основной файл
use strict;
use warnings;
# signal handling
$SIG{__DIE__} = sub {
my $error = @_;
chomp $error;
print "die: $errorn";
};
require mod;
mod->get_stat();
Модуль
package mod;
use strict;
use warnings;
use File::stat;
sub get_stat {
my $file_path = "test.txt";
my $file_size = stat($file_path)->size;
print $file_size;
}
1;
Это приведет к следующему выводу:
die: 1
die: 1
die: 1
die: 1
die: 1
4
Теперь, если я удалю свою пользовательскую обработку ошибок ИЛИ если я использую mod вместо require, кубики не будут отображаться.
Интересно видеть, что это действительно приводит к результату (test.txt составляет 4 байта), что означает, что статистика работает так, как должна.
Итак, почему я получаю эту ошибку? Это действительно ошибка? Игнорирует ли обработка ошибок perl по умолчанию ошибки, которые равны «1»?
Редактировать
Как заметил Лайнус Клин, причина, по которой я получаю «1», заключается в том, что я отображаю количество элементов в массиве.
Если вместо этого я распечатываю содержимое ошибки, я получаю следующую ошибку:
die: Your vendor has not defined Fcntl macro S_ISVTX, used at c:/Perl64/lib/File/stat.pm line 37.
die: Your vendor has not defined Fcntl macro S_IFSOCK, used at c:/Perl64/lib/File/stat.pm line 41.
die: Your vendor has not defined Fcntl macro S_IFBLK, used at c:/Perl64/lib/File/stat.pm line 41.
die: S_IFFIFO is not a valid Fcntl macro at c:/Perl64/lib/File/stat.pm line 41.
die: Your vendor has not defined Fcntl macro S_IFLNK, used at c:/Perl64/lib/File/stat.pm line 41.
4
Но все же я получаю ошибку, которую без пользовательской обработки ошибок я не получаю.
Комментарии:
1. require вернет последнюю исполняемую инструкцию из вашего пакета
2. Аааа… Так это Perl, работающий в Windows? Что это за ошибка?
3. Windows 7 с ActivePerl 5.12
Ответ №1:
Как объясняется в perlvar, из-за сбоя реализации $SIG{__DIE__}
перехватчики вызываются, даже когда код умирает внутри eval. При загрузке File::stat проверяется, какие константы поддерживает Fcntl на вашей платформе. Она улавливает ошибки, вызванные неподдерживаемыми константами, но не раньше, чем их увидит ваш хук.
Вы можете определить, находитесь ли вы в eval
, проверив значение $^S
. Если значение не равно 0, то вы находитесь в процессе оценки.
$SIG{__DIE__} = sub {
return unless defined $^S and $^S == 0; # Ignore errors in eval
my ($error) = @_;
chomp $error;
print "die: $errorn";
};
Вы не видите ошибок, когда вы use
вместо require
use
потому что require
это операция времени компиляции и %SIG
это операция времени выполнения (как указано в настройке, как указано в). Когда вы use mod
и это use
файл::stat, все это происходит до настройки вашего перехвата. У вас require mod
это происходит только после установки вашего перехвата.
Ответ №2:
Измените его на
my ($error) = @_;
В вашем примере кода вы используете скалярный контекст, который даст вам количество элементов в @_
, равное единице.
Комментарии:
1. Исправлено, спасибо, но все равно я получаю ошибку, которую без пользовательской обработки ошибок я не получаю.