Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Load all modules in directory

by ttcuberat (Sexton)
on Dec 10, 2003 at 18:41 UTC ( #313810=perlquestion: print w/replies, xml ) Need Help??

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

Fellow Monks, I'd like to load up all modules in a particular directory. I.e. instead of saying

use Module1; use Module2; use Module3;
I'd like to say something like:

BEGIN { @mods = glob("/home/cuberat/mods/*"); for (@mods) { use $_; } }
however, that fails miserably. Gracias!

-cube

Replies are listed 'Best First'.
Re: Load all modules in directory
by batkins (Chaplain) on Dec 10, 2003 at 19:56 UTC
    As others have, suggested, require is the answer. However, in order to get the full functionality of use, you should call import on the package you just required.
    BEGIN { @mods = glob("/home/cuberat/mods/*"); for (@mods) { require $_; $_->import; } }
    Also, I'm not sure if this is intentional, but globbing those files leaves the .pm on, which may not be what you want. Try adding
    s{.pm}{};
    to your for loop before the require.
    Are you sure it was a book? Are you sure it wasn't.....nothing?
      Also, I'm not sure if this is intentional, but globbing those files leaves the .pm on, which may not be what you want.

      Yes yes yes yes yes yes.

      Always verify that the data you are trying to use is of the correct format. I would recommend doing a print to <STDOUT> the elements of @mods to see if you are acutally getting what you need, and not getting something that is causing your code to choke.

      Hmm...I tried the above without success. It looks like the problem is that the functions in the Module are not being pulled into the current package

      . The require and import proceed without failure, but as soon as the function is called, I get
      Undefined subroutine &main::webcast_header called at multi_reporter.pl + line 133
      . Here is the current non-working thing that I'm trying:
      BEGIN { $mod_path="/home/tboyd/lib/site_perl/5.6.1/Tools/"; unshift @INC, $mod_path; my @mods = glob("$mod_path/*"); for (@mods) { s/.*\/(\w+\.pm)$/$1/gi; require $_; $_->import; } }
      The module that is being called works just fine under a "use" directive. Why might the import not be working? -C P.S. removing the .pm will make this thing barf on the "require".
        The require needs a file name and the import needs a package name. So you need to figure out how to require "/home/tboyd/lib/site_perl/5.6.1/Tools/ModuleA.pm" but import "Tools::ModuleA".

        You might want to see the thread about import.pm on perl5-porters for ideas about doing this or reasons not to.

Re: Load all modules in directory
by caedes (Pilgrim) on Dec 10, 2003 at 18:58 UTC
    You can't 'use' a filename, but you can 'require $filename'. That should work.

    -caedes

Re: Load all modules in directory
by hardburn (Abbot) on Dec 10, 2003 at 19:00 UTC

    Use require instead of use and it might work (be sure to prepend the directory path, though).

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      I've tried all these things and just can't get the damn thing to work. Here is the latest version (which still fails miserably)

      BEGIN { $mod_path "/home/tboyd/lib/site_perl/5.6.1/Tools/"; my @mods = glob("$mod_path*"); for (@mods) { require $_; } }
      Again...my intention is to load all the .pm files in that directory at compile time. Any other thoughts?

        The code given has syntax errors in it, but setting those aside: It-Works-For-Me(tm). Here it is with typos removed:

        BEGIN { my $mod_path = "/home/tboyd/lib/site_perl/5.6.1/Tools/"; my @mods = glob("$mod_path*"); for (@mods) { require $_; } }

        It should be noted that require is different from use in that use calls the module's import method and require does not. So, this could cause problems later on if you expect symbols to be imported (or these modules do something else nice for you in import).

        You may also want to change your glob to end in *.pm if you only want those files as there could be other files in the directory that aren't perlish.

        Would creating an "index" type module in that directory work? Or, is the list of modules too dynamic?

        It would be just a file Index.pm and look like this:

        require X; require Y; require Z;

        Unfortunately I don't have anywhere to test that right now.

        -Kurt

Re: Load all modules in directory
by pginmd (Initiate) on Dec 10, 2003 at 22:10 UTC
    The simplest thing I see is:
    BEGIN { # get list of modules my @mods = glob("/home/cuberat/mods/*"); for( @mods ) { s/\.pm$//i; #strip .pm from end of file eval "use $_"; #use the module!\ } }
      I concur with the "eval use".

      I have an application which currently uses this system and it works perfectly. You may want to check $@ for problems during the execution of the eval, but otherwise all is well.

      In my usage, this technique allows me to include OS-specific modules and code while leaving the main application oblivious to the OS-specific differences. I am basically using $^O ($OSNAME) to decide what modules to load with "eval use".

      The application in question is a custom build system. I have a function that is called "build_installer" that is really implemented 5 different ways on different platforms, all without any sort of if blocks. I simply implemented the function 5 different times in 5 different modules and pick the right one at runtime based on the OS the user is running. This way, the Win32 version can use Win32 modules without caring about not being able to run those under Linux, etc.

        Don't do that. String eval is inefficient. You get the same results with eval { require $modname; $modname->import(); };
Re: Load all modules in directory
by PodMaster (Abbot) on Dec 10, 2003 at 18:46 UTC
    Hi. use is a function, so `perldoc -f use' (that should clear everything up).

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Load all modules in directory
by AcidHawk (Vicar) on Dec 11, 2003 at 13:50 UTC

    just a thought.. but what is to stop you putting in malicious.pm in /home/cuberat/mods/ which does a rm -rf type thing..?

    -----
    Of all the things I've lost in my life, its my mind I miss the most.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://313810]
Approved by coreolyn
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2021-10-20 08:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My first memorable Perl project was:







    Results (79 votes). Check out past polls.

    Notices?