Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

What happens when you load the same module twice?

by periapt (Hermit)
on Feb 10, 2005 at 14:19 UTC ( [id://429731]=perlquestion: print w/replies, xml ) Need Help??

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

In this meditation, An Interesting Gotcha With use/require, I pondered a little warning involving the loading of the same module twice due to the case insensitivity of the Windows platform. I believe I understand why the warning occurred but I am not sure I understand how. Please consider my reasoning ...

Each package is compiled in its own namespace regardless of how it was brought into the picture which means in this context that functions are compiled and typeglobs to those functions are loaded into the package symbol table etc.. Functions are imported into (or exported from) a package by aliasing the function typeglobs in one package into the symbol tables of another (camel book 2nd ed pg 294).

Consider this case, a main program goes along and calls "use File::Basename;". The package namespace File::Basename is created, functions are compiled and, since File::Basename exports its function by default, the appropriate aliases to those functions are loaded into the symbol table for main::. A little while later, a library module is loaded that also "uses" File::Basename referencing the module with a different to perl but not to the OS syntax (File::Basename vs File::BaseName). Since the OS understands this to be the same file, File::Basename is again loaded. However, the namespace File::Basename already exists, so perl just recompiles the functions which resultes in the "subroutine redefined in File::Basename ... " warning (see readmore). This leads me to believe that what is happening is happening inside the File::Basename namespace. This belief is supported by the fact that the warning references only File::Basename and not the main or library packages in any way.

So far this makes sense, my question is, then, if the warning is not relevent to the main:: or library namespaces, why did the warning stop when I suppressed all automatic subroutine exporting to those packages? If I load File::Basename with the statement "use File::Basename();" in either main or the library (or both), I do not get the warning all else being the same. This suggests that the redifinition is occuring through or relative to the main:: or library namespaces which seems to contradict my previous reasoning.

What am I missing about package loading and namespaces that would reconcile these two behaviours?

Update:

Thanks for the great comments. I'm still not sure I have my answer though. Theoretically, the use statements in the main and library modules are in seperate namespaces. the main program does not import anything from the library module which implies that when File::Basename is "used", it is exporting its functions into distinct namespaces so there shouldn't be a clash. But there is which implies that File::Basename is exporting its functions into the same namespace. But which one? and why? I've looked at Basename.pm and I can't see where this might be happening. Something in the Exporter module maybe? And, if the clash is in the File::Basename namespace why does turning off automatic exportation stop the warning? Any ideas where I might go to research this further?

# stripped down test code #!/usr/local/ActivePerl-5.6/bin/perl use strict; use warnings; use diagnostics; use File::BaseName; printf("%-45s%-s\n",$_,$INC{$_}) foreach (sort keys %INC); package prob_func; sub secondfunc{ use File::Basename; return; } __OUTPUT__ #(relevent parts only) Subroutine fileparse_set_fstype redefined at C:/Program Files/Perl/lib/File/Basename.pm line 152 (#1) (W redefine) You redefined a subroutine. To suppress this warning +, say { no warnings; eval "sub name { ... }"; } Subroutine fileparse redefined at C:/Program Files/Perl/lib/File/Basen +ame.pm line 166 (#1) Subroutine basename redefined at C:/Program Files/Perl/lib/File/Basena +me.pm line 222 (#1) Subroutine dirname redefined at C:/Program Files/Perl/lib/File/Basenam +e.pm line 235 (#1) File/BaseName.pm C:/Program Files/Perl/lib +/File/BaseName.pm File/Basename.pm C:/Program Files/Perl/lib +/File/Basename.pm

PJ
use strict; use warnings; use diagnostics;

Replies are listed 'Best First'.
Re: What happens when you load the same module twice?
by dragonchild (Archbishop) on Feb 10, 2005 at 14:30 UTC
    use is really the following code:
    use My::Module @args; # This becomes ... BEGIN { require My::Module; My::Module->import( @args ); }

    require is approximately the following code:

    require My::Module; # This becomes ... sub require { my ($name) = @_; (my $filename = $name) =~ s!::!/!g; $filename .= '.pm' if $name =~ /::/; unless ( exists $INC{ $filename } ) { # Load the file into memory, figuring out which of @INC to use +. # Put the full pathname into $full_path_name $INC{ $filename } = $full_path_name; } }

    So, if a module has already been loaded, it won't be loaded again, but its import() will be called again (as tye noted in the original thread).

    Your confusion is arising because you're attempting to load File::BaseName and File::Basename on case-insensitive operating system. Because it's case-insensitive, the check against %INC is subverted. On case-insensitive operating systems, the following version of require may be more appropriate:

    sub require { my ($name) = @_; ########## THIS IS ADDED $name = lc $name; ########## TO HERE (my $filename = $name) =~ s!::!/!g; $filename .= '.pm' if $name =~ /::/; unless ( exists $INC{ $filename } ) { # Load the file into memory, figuring out which of @INC to use +. # Put the full pathname into $full_path_name $INC{ $filename } = $full_path_name; } }

    That should appropriately fix things. (But, it won't catch things like use Strict; - that lc fix would have to be part of use, which may not be a bad thing.)

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

      That should appropriately fix things.
      Will it? Sure, you don't get warnings if you do:
      use File::Basename; use File::BaseName;
      as the second use will not do anything. But if you remove the first one, or if you swap the two statements, File::Basename->import() won't be called, as Perl will try to call File::BaseName->import(), which doesn't exists so Perl will silently go on.

      This will lead to mysterious behaviour, that may be hard to debug.

        File::Basename->import() won't be called, as Perl will try to call File::BaseName->import(), which doesn't exists so Perl will silently go on

        You're describing the current behavior. His change, whatever other implications it may have, would not affect that.

        Update: to clarify my statement for Anonymous Monk, I meant that adding the lc $name doesn't change whether use File::BaseName would call the right import routine, or not.

      I thought his question was why do the warnings go away when you add () to one of the use statments. I'm not sure how your answer answers that.


      ___________
      Eric Hodges
        Because calling 'use File::Basename();' tells the compiler to import an empty list -- in other words, do not import anything. The issue at hand is that File::Basename and File::Basename are both trying to import subroutines into the main:: namespace by default.
Re: What happens when you load the same module twice?
by rir (Vicar) on Feb 10, 2005 at 19:01 UTC
    In the specific degenerate case given Perl does load the code twice. So it sees the code twice and complains that the Package::rout is defined twice. The exporting and importing of names is not germaine to the warning. People and Perl are being confused by OS limitations.

    Be well,
    rir

    --
    Here's a nickel, kid, get yourself a real filesystem. And keep the change.

      The fact that you're referring to Win32 (and VMS) as a degenerate case is absolutely delicious. ++!

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Re: What happens when you load the same module twice?
by Sandy (Curate) on Feb 10, 2005 at 22:15 UTC
    This affect is not limited to loading the same module twice, as it will happen if you load two modules that export subroutines of the same name (in this example 'foo').

    I presume this is a warning to prevent incompatible modules being used at the same time?

    For example

    one.pm

    #!/usr/bin/perl -w use strict; package one; require Exporter; our @ISA = ("Exporter"); our @EXPORT = qw(foo); sub foo { print "how do you do\n"; }
    two.pm
    #!/usr/bin/perl -w use strict; package two; require Exporter; our @ISA = ("Exporter"); our @EXPORT = qw(foo); sub foo { print "Salut toi! Ca va?\n"; }
    trial.pl
    #!/usr/bin/perl -w use strict; use one; use two; foo();
    result of running trial.pl
    [~/] perl trial.pl Subroutine main::foo redefined at /usr/local/lib/perl5/5.8.2/Exporter. +pm line 60. at trial.pl line 4 Salut toi! Ca va?
    Note, if you switch the use statements, main::foo points to one::foo instead of two::foo

    modified trial.pl

    #!/usr/bin/perl -w use strict; use two; use one; foo();
    result of running modified trial.pl
    [~/] perl trial.pl Subroutine main::foo redefined at /usr/local/lib/perl5/5.8.2/Exporter. +pm line 60. at trial.pl line 4 how do you do

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2024-03-29 00:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found