Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Overriding the built-in require function

by /dev/urandom (Beadle)
on Feb 04, 2008 at 19:44 UTC ( [id://666068]=perlquestion: print w/replies, xml ) Need Help??

/dev/urandom has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I want to figure out when certain modules are being loaded, and for this reason, I want to override require. So far I've almost managed to achieve what I wanted. I've overridden require, and it is called. The problem is, that it's not called with the module actually required by the user. For instance, if I want to require Net::Ping, I will receive all of its requirements, but I will not receive it. Here is my test script, which illustrates the issue:
#!/usr/bin/perl use strict; *CORE::GLOBAL::require = sub { CORE::require($_[0]); print $_[0], "\n" if $_[0] eq 'Net/Ping.pm'; }; require Net::Ping; my $p = Net::Ping->new;
What am I missing here? Also, if there's a better way of figuring out when modules are loaded (without having to modify the modules themselves), it would be a better solution.

Replies are listed 'Best First'.
Re: Overriding the built-in require function
by moritz (Cardinal) on Feb 04, 2008 at 19:52 UTC
    Wrap your substitution in a BEGIN block, then it works:
    BEGIN { *CORE::GLOBAL::require = sub { CORE::require($_[0]); print $_[0], "\n"; }; }
      excellent. that indeed seemed to work. thank you very much.
Re: Overriding the built-in require function (@INC)
by tye (Sage) on Feb 04, 2008 at 21:09 UTC

    You can also push a code ref (that returns undef) onto the front of @INC:

    BEGIN { unshift @INC, sub { my( $self, $file )= @_; print "Searching for $file...\n"; return; }; } require Net::Ping;

    See require for more details and other options.

    - tye        

      That would not serve my purposes, as any modules in question will not yet be loaded when the subref receives it.
        That's precisely the point: @INC is the list of paths that perl will search when it goes to load your module. If you put a code ref into @INC, perl will recognize it and execute it (rather than treating it as a path to search). By pushing your sub onto the front of @INC, you'll ensure that perl checks it first. By returning undef, you'll cause perl to keep looking until it finds the real path.

        The very end of the doc that tye linked, require, describes this in detail. The same @INC method works for use.

      But this of course fails if someone happens to do

      BEGIN { unshift @INC, sub { ... } } use lib 'somewhere/special'; require Net::Ping; # Resolves to "somewhere/special/Net/Ping.pm".
      as lib also unshifts @INC. This accident may not be obvious if it's a module that uses lib.

      For many purposes it works, but one should be aware of that it's not bullet proof against accidents.

      lodin

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (6)
As of 2024-03-19 02:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found