Trapping Errors in require or use
Problem
You need to load in a module that might not be present on your system. This normally results in a fatal exception. You want to detect and trap these failures.
Solution
Wrap the require or use in an
eval
, and wrap the
eval in a BEGIN block:
# no import
BEGIN {
unless (eval "require $mod") {
warn "couldn't load $mod: $@";
}
}
# imports into current package
BEGIN {
unless (eval "use $mod") {
warn "couldn't load $mod: $@";
}
}Discussion
You usually want a program to fail if it tries to load a module that
is missing or doesn’t compile. Sometimes, though, you’d
like to recover from that error, perhaps trying an alternative module
instead. As with any other exception, you insulate yourself from
compilation errors with an eval.
You don’t want to use eval
{
BLOCK
},
because this only traps run-time exceptions and
use is a compile-time event. Instead, you must use
eval
"string", to catch
compile-time problems as well. Remember, require
on a bareword has a slightly different meaning than
require on a variable. It adds a
".pm" and translates double-colons into your
operating system’s path separators, canonically
/ (as in URLs), but sometimes
\, :, or even
. on some systems.
If you need to try several modules in succession, stopping at the first one that works, you could do something like this:
BEGIN { my($found, @DBs, $mod); $found = 0; @DBs = qw(Giant::Eenie Giant::Meanie Mouse::Mynie Moe); for $mod (@DBs) { if (eval "require $mod") { $mod->import(); ...