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.)