http://qs321.pair.com?node_id=187462

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

Hello Monks,

I am writing a small app that needs to be able to use modules on command. Each module has the same set of subs but they all do their duties diffrently. The problem I am facing is that I seem to be able to only require a file once. For instance:
# Both modules have todo(); require "/path/to/something.pm"; # sets todo() require "/another/pathto/diffrent.pm"; # overwrites todo() require "/path/to/something.pm"; # doesn't do anything
still leaves me using the diffrent module. How can I reload a module? Please enlighten me!

Replies are listed 'Best First'.
Re: Reloading modules more than once
by abaxaba (Hermit) on Aug 04, 2002 at 07:14 UTC
    I guess my first question: Are these required files just collections of subroutines with a .pm extention, or are they actual packages? Against my gut, I'll assume that they're packages, based on the .pm extension in the filename.

    Based on that assumption:

    #!/perl use strict; use lib qw(/path/to /another/pathto); use diffrent; use something; something::todo(arg1,arg2); diffrent::todo(arg3,arg4);
    Another option is to take advantage of polymorphism, and some OOP. This can especially be an attractive choice if you find yourself with a lot of similar code between the two files:
    package something; @something::ISA=qw(basePack); sub todo { #something::todo code in here } package diffrent; @diffrent::ISA=qw(basePack); sub todo { #diffrent::todo code in here } package basePack sub new { return bless({},shift); } sub act { my $self=shift; $self->todo(@_); } #package main. #!/perl use strict; use lib qw(/path/to /another/pathto); use diffrent; use something; my $something=new something; my $diffrent = new diffrent; $something->act($arg1, $arg2); #something::todo; $diffrent->act($arg3,$arg4); #diffrent::todo;

    Of course, all of this can be averted. If you know when to "reload" sub todo, then you ought to know when it should be called. Just rename one of the todo subs to something else.

    ÅßÅ×ÅßÅ
    "It is a very mixed blessing to be brought back from the dead." -- Kurt Vonnegut

Re: Reloading modules more than once
by Zaxo (Archbishop) on Aug 04, 2002 at 07:03 UTC

    Two other issues come into this. What is imported? What namespaces do we subclass?

    An old style 'foo.pl' library by default exports everything it defines, so two requires may act as you fear, except that the last executed require provides the visible &todo. Perl modules are expected to establish their own namespace and not walk on each other's definitions.

    In your example, something.pm may call itself package something; internally, so its &todo is addressed as &something::todo while the other is addressed as 'different::todo(@things). Calling require happens at runtime, so you may need to import the routines you want.

    If you place the module namespace on your own namespace's @ISA at some time, you inherit whichever &todo appears first in a depth-first search of @ISA.

    After Compline,
    Zaxo

Re: Reloading modules more than once
by danger (Priest) on Aug 04, 2002 at 13:54 UTC

    To answer your specific question, the %INC hash keeps track of what has been loaded via do, require, or use --- if you want to re-require a file, simply delete its entry in the %INC hash and require it again (see the %INC entry in the perlvar manpage). However, you may want to rethink your design --- with more information on why you want to do this and what problem you are trying to solve, we might be able to offer better solutions.

Re: Reloading modules more than once
by sauoq (Abbot) on Aug 04, 2002 at 08:17 UTC

    Well, you can probably get the sort of functionality you want from the Safe module. I did some similar things using a stripped down version of Safe to help implement plugins. I simply took out all of the stuff for allowing and disallowing different operators. It made sense to do this because I wasn't using it as a container to "safely" evaluate untrusted code but as a way to isolate trusted code. If I recall correctly, I really wanted to be able to unload modules.

    I should point out that it was several years ago that I did this. Perl was probably at 5.002. I've rarely used Safe.pm since. I'm not sure what, if anything, has changed. It probably isn't the best way to do what you want and even if you do use it, it'll take some creativity. I only mention it because it is there and it might be worth knowing about.

    -sauoq
    "My two cents aren't worth a dime.";
    
(tye)Re: Reloading modules more than once
by tye (Sage) on Aug 04, 2002 at 17:49 UTC

    See require. For efficiency, it will only load the same file once. You can override this by doing:     delete $INC{"/path/to/somthing.pm"}; before you try to require that file subsequent times.

    You'll likely still run into problems because loading the same code twice isn't the same as loading it once. For example, you'll likely get warnings for each subroutine because they are getting redefined.

    There are several techiniques you can try to use to "clear" the package before you reload so that reloaded module is more likely to act like it has never been loaded before. However, none of them work perfectly. For example, I haven't found a good way to reload the module such that other modules that had previously had routines exported to them would see the new routines instead of the old ones.

    For example, there is Apache::Reload. See also Reloading Modules.

            - tye (but my friends call me "Tye")