ggg has asked for the wisdom of the Perl Monks concerning the following question:

Greetings.

I'm looking for a way to tell if a series of modules has loaded without having the script die on failure to load. My only idea so far is shown below, but it doesn't work. Out of desperation, I've tried backticks around use CGI but, predictably, that fails also. I don't want to use a use CGI or die kind of construct because I want feedback to know if all the modules loaded or which (if any) modules failed to load.
Is there a way to do this?

if (use CGI){ print "use CGI worked\n"; } else{ print "failed\n"; }
ggg

Replies are listed 'Best First'.
Re: feedback on successful module loading
by ikegami (Patriarch) on Oct 07, 2004 at 14:47 UTC
    BEGIN { eval { use CGI; }; if ($@) { print "failed\n"; } else { print "use CGI worked\n"; } }

    It's a rather odd thing to do, however. You might want to use fatalstobrowser of whichever modules does that (Carp?)

Re: feedback on successful module loading
by ccn (Vicar) on Oct 07, 2004 at 14:42 UTC

    You can use eval and check $@ for this

Re: feedback on successful module loading
by Marcello (Hermit) on Oct 07, 2004 at 15:29 UTC
    I always use:

    my $result = eval "use ModuleName; 1"; if (!$result) { ... }
Re: feedback on successful module loading
by diotalevi (Canon) on Oct 07, 2004 at 22:30 UTC

    That wouldnt work. The use() is executed during the parsing of the BEGIN block and so is already over by the BEGIN's runtime starts. Normally you'd write this using require.

    BEGIN { eval { require CGI } or print "failed\n"; }
Re: feedback on successful module loading
by ggg (Scribe) on Oct 07, 2004 at 18:58 UTC
    Well, this is what I've settled on. Works great. Now I can upload variations of this to the several ISPs I'm involved with and be able to tell which modules they have available.
    Many thanks to you all!
    #!/opt/bin/perl -w print "running $0 in Perl $]\n"; my $result = eval "use CGI; 1"; if ($result) { print "CGI loaded\n"; } else { print "CGI failed\n"; } print "$@\n"; my $result = eval "use HTML::Template; 1"; if ($result) { print "Tmplt loaded\n"; } else { print "Tmplt failed\n"; } print "$@\n";
    ggg
      You should wrap all that in a BEGIN block if you want the imports from those "use" to act in a traditional fashion. Otherwise, you've essentially turned a use into a require, sorta.

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a reply.

      You can make your code shorter by writing your code only once and putting your modules to test into a list.

      #!/opt/bin/perl -w print "running $0 in Perl $]\n"; for ( qw( CGI HTML::Template ) ) { print eval "require $_" ? "$_ ok\n" : "$_ failed: $@\n" }
        I was going to work on putting the module names into a DATA file and building the working script with another script. The result would have been just as long, but I wouldn't have written it by hand. I like your idea better. It has class!
        ggg