I have run into a situation with dynamically load available modules at runtime via eval. There is magic afoot I don't fully appreciate, so I am hoping someone can point to the right doc/direction on what is going on.

I have a fairly large codebase which needs to be deployed in a variety of situations/environments. Given the nature of the code, it can have an excessive number of module requirements to cover all the scenarios it can be leveraged for. Instead of doing some type of preinspection of the available modules and then reconfiguring the codebase on the fly or trying to download modules from CPAN, I wanted to wait until runtime and let user configurable data drive what modules should be loaded.

There are 2 main usage patterns, simply use()ing a module, and use()ing a module with a list of keywords to import into the application (IE. use Time::HiRes; vs use Time::HiRes qw(gettimeofday tv_interval). So a simple hash gets the trick done in terms of handling the data requirements The issue comes in with using eval causing keywords to not be imported into the namespace cleanly as far as I can tell.

After a number of posts about the syntax of the code not being valid I have replaced the code with the actual method being used. This is within a package which uses strict. I have added a third example which a contrived object using this information

#!/path/to/perl # This snippet works as expected use strict; use Time::HiRes qw(gettimeofday tv_interval); my $now = [gettimeofday]; sleep 2; # The below produces "Elapsed: 2.01233" print "Elapsed: ", tv_interval($now, [gettimeofday]), "\n";
#!/path/to/perl # This snippet *DOES NOT* work as expected use strict; my $toLoad = { 'CGI' => '1', 'Time::HiRes' => 'gettimeofday tv_interval', }; while ( my($module, $args) = each %$toLoad) { my $str = "use $module"; $str .= 'qw(' . $args . ')' if $args ne '1'; eval $str; # also tried eval {}, eval "", etc... } # END while each %$toLoad my $now = [gettimeofday]; sleep 2; # The below produces Elapsed: 0, print "Elapsed: ", tv_interval($now, [gettimeofday]), "\n";

Changing the line now = line to [gettimeofday()] it works, I assume by hinting to the runtime environment that this is in fact a routine and not a string.

So what is different within the eval expression that isn't within the standard use EXPR line?

#!/path/to/perl use strict; my $obj = {}; # For this example bless($obj, 'main'); # get some data via config and then my $status = $obj->loadPerlModule($configData); # Prints no warnings or errors under strict.. foreach my $module ( keys %$status ) { print "$module status: $status->{$module}\n"; } # This fails.. my $now = [gettimeofday]; sleep 2; # The below produces Elapsed: 0, print "Elapsed: ", tv_interval($now, [gettimeofday]), "\n"; # This succeeds my $newNow = [gettimeofday()]; sleep 2; # The below produces Elapsed: 2.02313, print "Elapsed: ", tv_interval($now, [gettimeofday()]), "\n"; # This is the actual method that loads the module. sub loadPerlModule { my $self = shift; my $modules = $self->asHash(@_); my $return = {}; foreach my $module ( keys %$modules ) { if ( $modules->{ $module } ne '1' ) { eval "use $module " . 'qw(' . $modules->{$module} . ');'; } else { eval "use $module"; } $return->{ $module } = ( $@ ) ? "Failed to use module: $@" : "Module loaded"; $@ = undef; } # END foreach my $module return $return; } # END sub loadPerlModule

use perl;
Everyone should spend some time pounding nails with their forehead for a while before they graduate to complicated stuff like hammers. - Dominus


In reply to Interesting behavior in eval block by l2kashe

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.