Obscure baffling "module not exported" error: can someone help mefind the cause?

Discussion in 'Perl Misc' started by Henry Law, Jan 31, 2008.

  1. Henry Law

    Henry Law Guest

    I have a bizarre problem with packages and I'm hoping that someone can
    help me find out what I'm doing wrong because I'm utterly stumped.

    The error is "not exported" for something that quite clearly is exported
    (details follow). The error disappears when one of several particular
    lines is deleted or commented out, one of which refers to a different
    Perl module altogether, not used anywhere in any of the code except for
    the "use" statement. And yet that completely unused module is specific
    to the error: simply replacing it with another, equally unused, module
    causes the error to disappear. Again, more details below.

    It's the most perplexing thing I've seen in all my years of debugging
    hardware and software systems and I'm forced to the conclusion that
    there's some corruption in the Perl installation itself, especially
    since the code compiles clean on another machine at ostensibly the same
    level (though the offending machine is newly-built). If someone can even
    point me in the direction of something to look at or try I'd be grateful.

    Now for the description of the code itself, which is a bit involved,
    despite my having condensed it down to its bare essentials. If you're
    prepared to help me make sense of this then
    http://www.lawshouse.org/perl/Problem.jpg shows the thing
    diagrammatically, with arrows drawn on. You can just about read the code
    in the image too.

    There are three modules: NFBT::ServerLib, NFBT::Utilities::Common and
    NFBT::Utilities::Server. There is some requirement in them for
    subroutines out of one or more of the others.

    A small test program "trynfbt.pl" includes "shadow_conv" from
    NFBT::Utilities::Server. The shadow_conv subroutine in
    Utilities::Server imports a subroutine from ServerLib, which in turn
    imports ":all: from Utilities::Common as well as the same shadow_conv
    sub from Utilities::Server. (I hope you're following this). The last
    piece of the jigsaw is that Utilities::Common imports XML::Twig::XPath.

    Running the test program trynfbt.pl gives (These line numbers may not be
    right because I knocked out blank lines and CR's to make the code
    smaller to post)

    "shadow_conv" is not exported by the NFBT::Utilities::Server module
    Can't continue after import errors at
    /usr/lib/perl5/site_perl/5.8.6/NFBT/ServerLib.pm line 28
    BEGIN failed--compilation aborted at
    /usr/lib/perl5/site_perl/5.8.6/NFBT/ServerLib.pm line 28.
    Compilation failed in require at
    /usr/lib/perl5/site_perl/5.8.6/NFBT/Utilities/Server.pm line 22.
    ... and three other lines that tell us no more.

    But shadow_conv *is* exported, unless my brain is addled.
    And removing any of the following lines makes the code run:

    The import of Utilities::Common(':all')
    The import of XML::Twig::XPath
    .. and, of course, the other "use" statements.

    Replacing XML::Twig::XPath with something else - I tried XML::Simple and
    even File::Basename - also makes the code run clean; it has to be that
    XML module despite the fact that it's never used. Eh?

    Lastly here is the actual code from the three modules and the test
    program. You might find the graphic easier ...

    Test Program
    ============
    #!/usr/bin/perl

    use strict;
    use warnings;

    use NFBT::Utilities::Server qw ( shadow_conv );

    print "This is the test routine $0\n";


    The three modules
    =================
    ------------------------------------------------------
    package NFBT::ServerLib;

    use 5.008;
    use strict;
    use warnings;

    require Exporter;
    our @ISA = qw(Exporter);

    our %EXPORT_TAGS = ( 'all' => [ qw(
    write_xml_twig
    ) ] );

    our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'}}, qw(
    write_xml_twig
    ) );

    print "This is NFBT::ServerLib\n";


    sub write_xml_twig {
    # The original write_xml_twig required several subroutines from
    # Utilities::Common and also 'shadow_conv'
    # Comment either of these out, problem disappears
    use NFBT::Utilities::Common ":all";
    use NFBT::Utilities::Server qw(shadow_conv); # "not exported"
    error here
    print "This is write_xml_twig in package NFBT::ServerLib\n";
    }

    1;

    --------------------------------------------------
    package NFBT::Utilities::Common;

    use 5.008;
    use strict;
    use warnings;

    require Exporter;
    our @ISA = qw(Exporter);

    our %EXPORT_TAGS = ( 'all' => [ qw(
    find_bkfile_by_id
    ) ] );

    our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'}}, qw(
    find_bkfile_by_id
    ) );

    sub find_bkfile_by_id {
    print "This is subroutine find_bkfile_by_id in package
    NFBT::Utilities::Common\n";
    use XML::Twig::XPath; # Comment this out, problem disappears. It
    has to be
    # XML::Twig::XPath, apparently. XML::Simple and File::Basename cause
    the problem to
    # disappear.
    }

    1;

    ------------------------------------------------------
    package NFBT::Utilities::Server;

    use 5.008;
    use strict;
    use warnings;

    require Exporter;
    our @ISA = qw(Exporter);

    our %EXPORT_TAGS = ( 'all' => [ qw(
    shadow_conv
    ) ] );

    our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'}}, qw(
    shadow_conv
    ) );

    sub shadow_conv {
    # The original shadow_conv used write_xml_twig
    use NFBT::ServerLib qw(write_xml_twig); # Comment this out, problem
    disappears
    print "This is subroutine shadow_conv in package
    NFBT::Utilities::Server\n";
    }

    1;

    --

    Henry Law Manchester, England
     
    Henry Law, Jan 31, 2008
    #1
    1. Advertising

  2. Re: Obscure baffling "module not exported" error: can someone helpme find the cause?

    Henry Law wrote:
    > I have a bizarre problem with packages and I'm hoping that someone can
    > help me find out what I'm doing wrong because I'm utterly stumped.
    >
    > The error is "not exported" for something that quite clearly is exported
    > (details follow). The error disappears when one of several particular

    <snip>

    > There are three modules: NFBT::ServerLib, NFBT::Utilities::Common and
    > NFBT::Utilities::Server. There is some requirement in them for
    > subroutines out of one or more of the others.

    You appear to have circular dependencies between these modules, and I'd
    guess that the mutual importing is confusing the import/export mechanism.

    There is a brief discussion at

    http://www.perlmonks.org/?node_id=473692

    I'd try breaking the circular dependencies for a start.



    > package NFBT::ServerLib;

    <snip>
    > sub write_xml_twig {
    > # The original write_xml_twig required several subroutines from
    > # Utilities::Common and also 'shadow_conv'
    > # Comment either of these out, problem disappears
    > use NFBT::Utilities::Common ":all";
    > use NFBT::Utilities::Server qw(shadow_conv); # "not exported" error
    > here
    > print "This is write_xml_twig in package NFBT::ServerLib\n";
    > }


    This is an unrelated issue, but "use"ing happens at compile-time.
    Putting the use statement inside the subroutine does not limit its scope
    or control when it is executed. perldoc -f use has the gory details.

    Mark
     
    Mark Clements, Jan 31, 2008
    #2
    1. Advertising

  3. Henry Law

    Guest

    On Jan 31, 12:20 pm, Henry Law <> wrote:


    (snipped)

    >
    > Now for the description of the code itself, which is a bit involved,
    > despite my having condensed it down to its bare essentials. If you're
    > prepared to help me make sense of this thenhttp://www.lawshouse.org/perl/Problem.jpgshows the thing
    > diagrammatically, with arrows drawn on. You can just about read the code
    > in the image too.
    >
    > There are three modules: NFBT::ServerLib, NFBT::Utilities::Common and
    > NFBT::Utilities::Server. There is some requirement in them for
    > subroutines out of one or more of the others.
    >


    (snipped)

    First of all, you have a couple of modules that mutually use
    each other, namely:

    NFBT::ServerLib and
    NFBT::Utilities::Server

    this is generally a bad idea and you should consider refactoring;
    see the discussion here:

    http://www.perl.com/pub/a/2000/07/p5pdigest/THISWEEK-20000709.html#Mutual_use

    Remember that use statements are collected into the BEGIN block (even
    if
    you embed them inside a subroutine) to be evaluated at compile-time
    -- see 'perldoc perlmod'.

    So, I'd suggest that you refactor. A quick "work-around" would be
    that
    in NFBT::Utilities::Server, you change

    use NFBT::ServerLib

    to

    require NFBT::ServerLib;
    import ServerLib (qw/write_xml_twig/);

    in which case:

    #!/usr/bin/perl
    use strict;
    use warnings;
    use NFBT::Utilities::Server qw ( shadow_conv );

    print "This is the test routine $0\n";
    shadow_conv();

    ought to run as expected (because 'require', unlike 'use'
    is evaluated at run-time).

    --
    Hope this helps,
    Steven
     
    , Jan 31, 2008
    #3
  4. Henry Law

    Henry Law Guest

    Re: Obscure baffling "module not exported" error: can someone helpme find the cause?

    wrote:

    > First of all, you have a couple of modules that mutually use
    > each other, namely:
    >
    > NFBT::ServerLib and
    > NFBT::Utilities::Server
    >
    > this is generally a bad idea and you should consider refactoring;
    > see the discussion here:
    >
    > http://www.perl.com/pub/a/2000/07/p5pdigest/THISWEEK-20000709.html#Mutual_use


    Steven, and Mark Clements in another post, thank you very much. Even
    the little I knew about how Perl programs actually hurl themselves into
    action should have pointed me to the fact that this kind of circular
    "use"-ing isn't a good idea. I'll have a go at some refactoring; if
    that doesn't work (sounds like intellectual heavy lifting) then I might
    resort to using BEGIN blocks or "require".

    But one more thing: can you think of a reason why this problem has
    suddenly hit? I'm doing a test installation (having written a configure
    program to produce a Makefile) on a fresh machine, running FC6 (Perl
    5.8.8 but I don't have a perl -v handy), but the code is built on my
    development machine, FC5, also Perl 5.8.8, on which it runs perfectly,
    circular references notwithstanding. But I'll bash on with the
    refactoring anyway.

    --

    Henry Law Manchester, England
     
    Henry Law, Jan 31, 2008
    #4
  5. Henry Law

    Ben Morrow Guest

    Re: Obscure baffling "module not exported" error: can someone helpme find the cause?

    Quoth Mark Clements <>:
    > Henry Law wrote:
    > > I have a bizarre problem with packages and I'm hoping that someone can
    > > help me find out what I'm doing wrong because I'm utterly stumped.
    > >
    > > The error is "not exported" for something that quite clearly is exported
    > > (details follow). The error disappears when one of several particular

    > <snip>
    >
    > > There are three modules: NFBT::ServerLib, NFBT::Utilities::Common and
    > > NFBT::Utilities::Server. There is some requirement in them for
    > > subroutines out of one or more of the others.

    > You appear to have circular dependencies between these modules, and I'd
    > guess that the mutual importing is confusing the import/export mechanism.


    This *shouldn't* be a problem, providing Perl knows the exports early
    enough. Put the 'require Exporter; @ISA=...; @EXPORT=...;' stuff in a
    BEGIN block, *before* you use any modules that might recursively use
    this one.

    > This is an unrelated issue, but "use"ing happens at compile-time.
    > Putting the use statement inside the subroutine does not limit its scope
    > or control when it is executed.


    ....unless it's a lexically-scoped pragma like strict or warnings. The
    use still happens at compile time, but some of the effects of that are
    restricted to the lexical scope currently being compiled. This obviously
    doesn't apply to simply importing subs, which is an operation with
    global effect.

    Ben
     
    Ben Morrow, Jan 31, 2008
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Fonnesbeck

    baffling error-handling problem

    Chris Fonnesbeck, Jul 28, 2005, in forum: Python
    Replies:
    2
    Views:
    401
    Scott David Daniels
    Jul 28, 2005
  2. Scotty
    Replies:
    3
    Views:
    334
    Andre Kostur
    Jun 8, 2007
  3. TimS
    Replies:
    5
    Views:
    176
    Jeff Cochran
    Dec 26, 2003
  4. Tom Cloyd

    baffling undefined method error

    Tom Cloyd, Mar 15, 2008, in forum: Ruby
    Replies:
    11
    Views:
    217
    Tom Cloyd
    Mar 17, 2008
  5. Spydo
    Replies:
    4
    Views:
    131
    Uri Guttman
    Feb 8, 2011
Loading...

Share This Page