"use module" and %INC and multiple requires to same perl file

K

kellinorman

I have a perl module - just a collection of related subroutines -
called AuditData.pm, which resides in
/usr/local/apache/htdocs/secure/modules. It was a large collection of
subroutines which was taking a long time to "require" as a plain old
..pl file, so I made it into an autoloading module. The perl scripts
that "use" the module reside one directory up, in
/usr/local/apache/htdocs/secure. AuditData.pm also "require"s a few
..pls that live up in the scripts directory - no problem, I just
"require" them using "./scriptName.pl" and that seems to work fine.
The problem seems to be whenever a script that is "require"d by
AuditData.pm, itself "require"s another script that is ALSO "require"d
by the original calling script. So.... if I have (bear with me
here):

/usr/local/apache/htdocs/secure/main.pl
----
require "script1.pl";
require "script2.pl";
use lib "./modules";
use AuditData;
....

and /usr/local/apache/htdocs/secure/modules/AuditData.pm:
----
require "./script1.pl";

and /usr/local/apache/htdocs/secure/script1.pl:
----
require "script2.pl";
&callToSubroutineInScript2();


I get the error (in my apache error log):
Can't locate auto/AuditData/script2.al in @INC (@INC contains:.....) at
../script1.pl line 724.

Line 724 is the &callToSubroutineInScript2.

I know it can't locate the script there (in
/usr/local/apache/htdocs/secure/modules/auto/AuditData) - it's up 3
levels (in /usr/local/apache/htdocs/secure) in the main script
directory. %INC has an entry for "script2.pl". @INC has an entry for
".", which should be /usr/local/apache/htdocs/secure, right? What am I
doing wrong? if I preface all requires with "./", will that fix the
problem?

Thanks in advance for any advice.
Kelli Norman
 
J

John Bokma

kellinorman said:
directory. %INC has an entry for "script2.pl". @INC has an entry for
".", which should be /usr/local/apache/htdocs/secure, right?

Are you sure about that? Print %INC to be sure.

Also read about use lib in case %INC doesn't have the right path.
 
K

kellinorman

I have printed %INC, and it contains an entry for "script2.pl". I have
printed @INC, and it has an entry for ".", and since the original
script (main.pl) is executed from /usr/local/apache/htdocs/secure, I
believe that's what "." is. I understand "use lib" - am using it when
I "use AuditData" in main.pl.

I'm thinking perl modules are really supposed to be object oriented
self-contained things, and not use files that are already included
elsewhere in execution. By the way, if I specify ' require
"./script2.pl" ' in script1.pl, I don't get the error. I don't think
this change will cause problems elsewhere, and that's what I'll
probably do if I don't get any other suggestions. I just don't want to
band-aid the scripts if the problem is really something else...

thanks
 
J

John Bokma

kellinorman said:
and it contains an entry for "script2.pl". I have
printed @INC, and it has an entry for ".", and since the original
script (main.pl) is executed from /usr/local/apache/htdocs/secure, I
believe that's what "." is. I understand "use lib" - am using it when
I "use AuditData" in main.pl.

IIRC '.' doesn't need to be set to the directory you expect it to be.
add

use lib '/usr/local/apache/htdocs/secure';

below:

use strict;
use warnings;

and before other use/require

I'm thinking perl modules are really supposed to be object oriented
self-contained things, and not use files that are already included
elsewhere in execution.

That would exclude inheritance, and hence no OO.
 
B

Brian McCauley

kellinorman said:
I'm thinking perl modules are really supposed to be object oriented
self-contained things, and not use files that are already included
elsewhere in execution.

It is quite OK for several modules to require() the same module.
Actually all but the first require() are simply NOPs. This doesn't
matter because a module loads into its own namespace and once it's
loaded it's loaded. If you load it with use() then it also may export
some parts of its symbol table into each of the calling namespaces.

But Perl4-style libraries are not modules. When you require a Perl4
library it loads into the caller's namespace. For this reason, as you
correctly observe, multiple Perl5-style modules cannot require the same
Perl4-style library.

In most situations the correct thing to do is to upgrade the Perl4
library to a Perl5 module. If you really need to retain Perl4
compatability (does anyone?) you can write a trivial wrapper module
that Perl5 scripts can use rather than loading the library directly.

In some cases you can get away with simply do()ing the library rather
than require()ing it. This loads multiple copies of the Perl4-library.

I could advise you further if I knew what the actual Perl4 libraries
you are using do.
By the way, if I specify ' require
"./script2.pl" ' in script1.pl, I don't get the error. I don't think
this change will cause problems elsewhere, and that's what I'll
probably do if I don't get any other suggestions.

All you are doing is changing where scipt2.pl first gets require()d
(recall that all but the first require are NOPs). Better than adding
still more require()s would be remove all but one.
 
K

kellinorman

Brian said:
kellinorman wrote:
....
But Perl4-style libraries are not modules. When you require a Perl4
library it loads into the caller's namespace. For this reason, as you
correctly observe, multiple Perl5-style modules cannot require the same
Perl4-style library.

In most situations the correct thing to do is to upgrade the Perl4
library to a Perl5 module. If you really need to retain Perl4
compatability (does anyone?) you can write a trivial wrapper module
that Perl5 scripts can use rather than loading the library directly.
Thanks Brian. That makes sense. Rewriting all my included .pl files
as modules sounds like it's probably the best solution. I'll try that.
I could advise you further if I knew what the actual Perl4 libraries
you are using do.
Mostly text processing and retreiving/storing/updating database records
for a web-based system.

Thanks again.
 
M

Michele Dondi

IIRC '.' doesn't need to be set to the directory you expect it to be.
add

use lib '/usr/local/apache/htdocs/secure';

I don't know if I understood the OP's problem clearly, but in what
that I *think* to be similar situations, I've used

use FindBin;
use lib $FindBin::Bin;

to great advantage.


Michele
 
B

Bart Lateur

kellinorman said:
I have
printed @INC, and it has an entry for ".", and since the original
script (main.pl) is executed from /usr/local/apache/htdocs/secure, I
believe that's what "." is.

It doesn't sound very secure. :)

Anyway, you can check, using the (standard) module Cwd, the function
cwd.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top