Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
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 ( [id://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.

Replies are listed 'Best First'.
Re: How can I prevent a module from being added to the %INC hash?
by ikegami (Patriarch) 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 syphilis (Archbishop) 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 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 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 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
Domain Nodelet?
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?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (3)
As of 2024-03-19 07:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found