use IO::Uncompress::Gunzip qw( gunzip $GunzipError );
is short for
BEGIN {
require IO::Uncompress::Gunzip;
import IO::Uncompress::Gunzip qw( gunzip $GunzipError );
}
and BEGIN
blocks are evaluated as soon as they are compiled. That means your code does:
- Compilation phase:
- Compile
eval
statement.
- Compiled
BEGIN
block.
- Compile
require IO::Uncompress::Gunzip;
- Compile
import IO::Uncompress::Gunzip qw( gunzip $GunzipError );
- Evaluate
BEGIN
block.
- Evaluate
require IO::Uncompress::Gunzip;
- Evaluate
import IO::Uncompress::Gunzip qw( gunzip $GunzipError );
- Compile
if
statement.
- Run phase:
- Evaluate (empty)
eval
statement.
- Evaluate
if
statement.
If an exception happens in step 1.1.2.1, the eval
run in step 2.1 won't catch it!
Solutions:
You started with something equivalent to
BEGIN {
require IO::Uncompress::Gunzip;
import IO::Uncompress::Gunzip qw( gunzip $GunzipError );
}
It's errors from require
you want to catch, so just add an eval
around the require
:
BEGIN {
eval { require IO::Uncompress::Gunzip }
or die "Error: IO::Uncompress::Gunzip not installed: $@";
import IO::Uncompress::Gunzip qw( gunzip $GunzipError );
}
You could also delay the use
getting compiled (and thus evaluated) by using eval EXPR
instead of eval BLOCK
:
BEGIN {
eval 'use IO::Uncompress::Gunzip qw( gunzip $GunzipError ); 1'
or die "Error: IO::Uncompress::Gunzip not installed: $@";
}
(I wish there was a good way of finding out if a module is installed. Even the first solution will catch other errors, the second even more.)