Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

An Interesting Gotcha With use/require

by periapt (Hermit)
on Feb 09, 2005 at 14:30 UTC ( #429395=perlmeditation: print w/ replies, xml ) Need Help??

I have recently encountered an interesting gotcha from the use/require functions. I had just added a library function to my general use library when I suddenly started getting a redefined subroutine warning for File::Basename (see below) from a program that had been running warning free until that moment. Both the main program and the new library function specify use File::Basename. It was always my understanding that use and require would not try to load a module a second time if it was already listed in %INC. A likely red herring here is that the main program does not actually import, call or otherwise reference the new library routine in the library module.

The key to the problem is (after a few hours of head scratching) that each routine calls File::Basename slightly differently which defines two seperate entries in %INC yet still loads the same module.

This all happens on a WinXP machine with Activestate 5.6.1. I haven't tried it on my Linux box yet. I'm guessing that this is a DOS/Win32 issue in that file names are not case sensative in that environment. Not groundbreaking, maybe, but an interesting gotcha none-the-less.
# 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

Update:

I forget to include the package statement before the sub prob_func definition. The warning occurs either way but my original problem occurred in seperate namespaces

Update:

Thanks for the great comments. The discussion did raise one or two other questions that I thought better moved to SOPW. Thanks again :o)

PJ
use strict; use warnings; use diagnostics;

Comment on An Interesting Gotcha With use/require
Select or Download Code
Re: An Interesting Gotcha With use/require
by japhy (Canon) on Feb 09, 2005 at 14:40 UTC
    It is purely a case-sensitivity issue. To Perl, File::BaseName and File::Basename are two different namespaces. As modules, they would be handled by File/BaseName.pm and File/Basename.pm (ordinarily). To Windows, however, those two files are the same.

    Perl won't load a module if it's already in %INC, but Perl doesn't see an entry for 'File/BaseName.pm', only for 'File/Basename.pm'.

    For an interesting artifact of this anomoly, try running this code:

    use Strict; $foo = 10;
    and see what happens. See if you can figure out why.
    _____________________________________________________
    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart

      That runs silently for me.
      I did a case-insensitive search for files, to check for any Strict.pm and only found "C:\perl\lib\strict.pm"

      So, it must be loading strict.pm successfully as there's no errors/warnings, but 'strict' isn't catching the undeclared variable.

      I'm stumped! What's going on then?

        Ponder the difference between strict->import() and Strict->import().

Re: An Interesting Gotcha With use/require
by dragonchild (Archbishop) on Feb 09, 2005 at 14:42 UTC
    I just tried it on Solaris.
    Can't locate File/BaseName.pm in @INC (@INC contains: ... )

    Commenting out the use on File::BaseName and leaving in the one for File::Basename means that everything works fine.

    I'm guessing you're right - it's an OS issue with case-sensitivity. VMS will probably have the same problem.

    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: An Interesting Gotcha With use/require
by perrin (Chancellor) on Feb 09, 2005 at 15:04 UTC
    I had just added a library function to my general use library when I suddenly started getting a redefined subroutine warning for File::Basename (see below) from a program that had been running warning free until that moment. Both the main program and the new library function specify use File::Basename.

    That should not be a problem if your library declares a package name. Don't make perl4-style libs that just dump all their functions into your main program -- you will regret it.

    It was always my understanding that use and require would not try to load a module a second time if it was already listed in %INC.

    They will still call import() a second-time though.

      That should not be a problem if your library declares a package name.
      What do you mean by that? Note that File::Basename is a standard module whose first line reads:
      package File::Basename;
      The problem isn't the library. The problem isn't the code either. The problem is the underlaying filesystem.

      To the OP: "Here's a nickle kid. Get yourself a better computer"

        Not File::Basename, but his library that uses it. There would not be any collision of imported names if that library was in a different namespace.
      This is one of the points that made it interesting. File::Basename exports its functions by default. The library is a standard perl 5 formatted module with a seperately defined namespace that doesn't export anything by default. In particular, the offending library routine is not imported or used by the parent program. Yet the clash occurs. However, if I turn off the default export behavior of File::Basename (by importing with "use File::Basename();") in either or both of the routines, the problem goes away on its own. Not exactly what I was expecting. What namespace is the default behavior exporting too in this case? the parent? If the export is to different namespaces, why the clash?

      I see I forgot to include a package statement ahead of the subroutine declaration in my original post so I can see where you would think everything was occuring in the same namespace. My apologies for the confusion.

      PJ
      use strict; use warnings; use diagnostics;
        As you can read in the followup to perrins comment, his comment is totally irrelevant, and only causes confusion. Your problem occurs because a subroutine gets defined twice. It has nothing to do with importing. See my example further down the thread - the one subroutine that's being redefined isn't exported.
Re: An Interesting Gotcha With use/require (a fix)
by tye (Cardinal) on Feb 09, 2005 at 16:57 UTC
      Is this useful for all programs regardless of whether they use classes or not?

      PJ
      use strict; use warnings; use diagnostics;

        It's useful (or can be) in programs that use use. Note that use (quoting the documentation) is equivalent to:

        BEGIN { require Module; import Module LIST; }

        and "import Module List" is "Module->import( List )", which is "using a class" even if 'Module' isn't object-oriented.

        If you never use use, then that code will never matter.

        - tye        

Re: An Interesting Gotcha With use/require
by fireartist (Chaplain) on Feb 09, 2005 at 17:02 UTC
    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 { ... }"; }

    Out of interest, does anyone know why the error message suggests wrapping "sub name { ... }" in an eval?

    use strict; use warnings; sub foo { print 'x' } { no warnings; sub foo { print 'y' } } foo();
    ...prints 'y' with no warnings for me.

      In your code, the first and second sub are declared at compile time. But if you want to dynamically declare a subroutine at run time, you need to wrap it up in an eval block so that that particular piece of code is evaluated only at run time.

Re: An Interesting Gotcha With use/require
by jacques (Priest) on Feb 10, 2005 at 01:07 UTC
    See also my win module.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://429395]
Approved by BrowserUk
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: (4)
As of 2014-11-29 08:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (204 votes), past polls