Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Obscure baffling "module not exported" error: can someone help mefind the cause?

Reply
Thread Tools

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

 
 
Henry Law
Guest
Posts: n/a
 
      01-31-2008
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
 
Reply With Quote
 
 
 
 
Mark Clements
Guest
Posts: n/a
 
      01-31-2008
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
 
Reply With Quote
 
 
 
 
attn.steven.kuo@gmail.com
Guest
Posts: n/a
 
      01-31-2008
On Jan 31, 12:20 pm, Henry Law <(E-Mail Removed)> 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/p5...tml#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
 
Reply With Quote
 
Henry Law
Guest
Posts: n/a
 
      01-31-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) 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/p5...tml#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
 
Reply With Quote
 
Ben Morrow
Guest
Posts: n/a
 
      01-31-2008

Quoth Mark Clements <(E-Mail Removed)>:
> 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

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
can someone help me with this baffling regex ? Spydo Perl Misc 4 02-08-2011 09:09 PM
yield example baffling - need help Tom Cloyd Ruby 3 01-16-2009 01:22 PM
Re: Baffling class not found problem laredotornado@zipmail.com Java 1 05-26-2005 04:56 PM
baffling 'file not found' error. I dare someone to solve this! TimS ASP General 5 12-26-2003 02:55 PM
Baffling question ASP .Net 4 11-09-2003 12:46 AM



Advertisments