die, warn and eval
| die and warn | |
| The $! variable | |
| eval | |
| autodie |
die and warn
die prints a message to standard error and ends the program with a non-zero exit code. warn prints the same message and keeps going. Both add the file name and line number when the message does not end with a newline.
my $file = "missing.txt";
warn "optional file missing\n" unless -e $file;
die "cannot continue: no data\n" unless -e $file;
print "never reached\n";
perl demo.pl
optional file missing
cannot continue: no data
Nothing reaches the last line: the die ends the program on the spot. Neither message carries a file name or line number, because both end with a newline.
The trailing newline is a switch, not a style choice: with it, Perl trusts your message as complete; without it, Perl appends the location so you can find the culprit. Keep the newline in messages a user will read, and drop it for internal assertions.
The $! variable
When a system call fails, the operating system reason lands in $!. Interpolating it into a die message turns cannot open into a sentence that names the problem.
open my $fh, "<", "/root/secret"
or die "open failed: $!\n";
perl demo.pl
open failed: Permission denied
In numeric context $! gives the raw errno value, which is useful in logs that a monitoring system will parse. In string context it gives the English text.
eval
eval runs a block and catches a die instead of letting it end the program. On success it returns the value of the block; on failure it returns undef and leaves the error message in $@.
my $result = eval {
die "bad input\n" if !defined $ARGV[0];
$ARGV[0] * 2;
};
if ($@) {
warn "recovered: $@";
} else {
print "result $result\n";
}
perl demo.pl
recovered: bad input
perl demo.pl 21
result 42
With no argument the block dies, the warn prints the caught message and the program carries on. Give it a number and the same block doubles it.
Two rules make eval safe to use. Check $@ immediately, before any other call can clear it, and keep the block small so you know exactly what it protects.
autodie
Writing or die after every open gets old. The autodie pragma makes the common system calls throw an exception on failure, so the happy path stays clean and one eval can catch everything.
use autodie;
my $ok = eval {
open my $fh, "<", "missing.txt";
my @lines = <$fh>;
print scalar @lines, " lines\n";
1;
};
warn "read failed: $@" unless $ok;
perl demo.pl
read failed: Can't open 'missing.txt' for reading: 'No such file or directory' at demo.pl line 4
The exception carries the file name and line number, because the message autodie builds has no trailing newline of its own. The line number is the open call, the fourth line of the program above.
autodie is in the core since Perl 5.10.1, so there is no install step. It covers open, close, mkdir, unlink and the other IO and filesystem calls, which is where most of the unhandled failures in small scripts come from.
Next: Modules and Exporter
Article author: Arthur Isaev