Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

How can I prevent a module from being added to the %INC hash?

by jacques (Priest)
on Oct 04, 2006 at 01:05 UTC ( #576223=perlquestion: print w/ replies, xml ) Need Help??
jacques has asked for the wisdom of the Perl Monks concerning the following question:

I would like to prevent a module (and all the modules that it uses) from being added to the %INC hash in my program.

If I could remove the modules after they were added, then that would be fine too. But how could I tell (without knowing offhand) in the %INC hash what modules are used by what modules?

I thought of setting something up with a BEGIN block, but that didn't make sense since my program uses many modules and I just want to prevent one (and the ones that it uses) from being added.

Thanks monks.

Comment on How can I prevent a module from being added to the %INC hash?
Re: How can I prevent a module from being added to the %INC hash?
by syphilis (Canon) on Oct 04, 2006 at 02:13 UTC
    I think you're on the right track with the BEGIN block. Here's an example that (I hope) removes Net::FTP and any modules loaded by Net::FTP from %INC:
    BEGIN { use strict; use warnings; use Carp; use Digest::MD5; our %inc_copy = %INC; }; use Net::FTP; %INC = %inc_copy; for(keys(%INC)) {print "$_: $INC{$_}\n"}

    Note that I explicitly loaded Carp.pm, and that Net::FTP also loads Carp.pm. Do you therefore require that Carp.pm not appear in %INC ?
    With the above example, Carp.pm still appears in %INC.

    Cheers,
    Rob
      One problem: What if you are putting the code above into a module and then use that module in a program? The %INC hash will contain all the modules that the program uses as well. And those modules will not be in the %INC hash when you assign it to %inc_copy.
        What if you are putting the code above into a module and then use that module in a program?

        I might be missing something here, but it still seems to work ok:
        ## My_Foo.pm package My_Foo; BEGIN { use strict; use warnings; use Carp; use Digest::MD5; our %inc_copy = %INC; }; use Net::FTP; %INC = %inc_copy; 1;
        ## test.pl use Math::BigInt; use My_Foo; for(keys(%INC)) {print "$_: $INC{$_}\n"}

        Net::FTP and the modules it loads are still missing from %INC.

        Cheers,
        Rob
Re: How can I prevent a module from being added to the %INC hash?
by sgifford (Prior) on Oct 04, 2006 at 02:27 UTC
    Just an interesting side note: I expected local %INC in a BEGIN block or an eval to automatically back out changes to %INC when the enclosing block finished, but that didn't work. I wonder why?...
      It doesn't work due to how BEGIN blocks and use statements are compiled/executed. If you take the use out of the equation, you can see that there's nothing special about %INC:

      For example, compare the difference between these two commands:

      perl -e'BEGIN{ eval "use Net::FTP;" } print %INC'

      and

      perl -e'BEGIN{ local %INC = %INC; eval "use Net::FTP;" } print %INC'

      The only difference between the two is the localization of %INC in the BEGIN block.

      Of course, doing an eval on the string is slow. The OP might want to use a require inside a BEGIN block, instead:

      BEGIN { # Hide the fact that our module was imported. local %INC = %INC; require Net::FTP; # call import() if necessary }
        Ah, I forgot about local. It worked. I have to do further testing in the morning. But it looks good so far. thanks
        Yup, that does seem to work. I swear I tried exactly that yesterday and it didn't work. I suspect the cost of string eval will be very small compared to the cost of loading and compiling the module.
Re: How can I prevent a module from being added to the %INC hash?
by ikegami (Pope) on Oct 04, 2006 at 02:35 UTC

    Perhaps you should be using do instead of require or use? It does add the module to %INC, but since %INC is not checked, you can execute the "module" multiple times.

    do should be used for "modules" with no package statement. require or use should be used with modules with a package statement.

    # config.pl # --------- $var = 'test';
    # main.pl # ------- use strict; use warnings; our $var; do 'config.pl'; print($var);
      Is it possible to use a module another way? For example, putting a reference to a subroutine that uses a module into @INC? I think the docs indicate that only the reference is added to %INC. But I have never tried adding a code reference to @INC.

        Yes, read the module file and eval it.

        What are you trying to do? What's the end goal?

Re: How can I prevent a module from being added to the %INC hash?
by Tanktalus (Canon) on Oct 04, 2006 at 03:31 UTC

    Perhaps I'm being somewhat dense here, but ... why?

    /me smells an XY Problem although that could actually be dinner.

Re: How can I prevent a module from being added to the %INC hash?
by diotalevi (Canon) on Oct 04, 2006 at 15:59 UTC

    This is a strange problem and it doesn't sound like you're solving a sane problem. It's easy enough to modify a hash - just remove the stuff that's added.

    my %pre_existing_INC; BEGIN { @pre_existing_INC{ keys %INC } = () } use Your::Module; BEGIN { delete @INC{ grep { not exists $pre_existing_INC{$_} } keys %I +NC } }

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://576223]
Approved by friedo
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2015-07-04 19:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (60 votes), past polls