Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Any way to access global variable in Perl script from one module file?

Reply
Thread Tools

Any way to access global variable in Perl script from one module file?

 
 
Michael Yang
Guest
Posts: n/a
 
      05-10-2007
I want to access one global variable saved in the main script from
another one module. Here is what it looks like:

A.pl: the main program, with one variable, e.g., $var, declared as
global.
#!/usr/bin/perl
use strict;
use warnings;
use B;
our $var = "hello";
testB();

B.pm: the module file, from which I want to access the $var variable
in A.pl
#!/usr/bin/perl
package B;
use strict;
use warnings;
require "A.pl"; ###########Actually I don't like this way, due
to some problem
sub testB{
print "In B.pm, the variable is $var\n";
############Here I want the $var value in A.pl be accessible.
}

Is there a way doing this like in C language, we just need to declare
it in B.pm, that the $var has been defined elsewhere, so it won't be
checked during compile time but in runtime.

The reason I don't want use 'require' statement, is the A.pl will be
evaluated. But I only need it to check the declaration and assignment
of the variable $var.

Thanks all.

 
Reply With Quote
 
 
 
 
Jens Thoms Toerring
Guest
Posts: n/a
 
      05-10-2007
Michael Yang <(E-Mail Removed)> wrote:
> I want to access one global variable saved in the main script from
> another one module. Here is what it looks like:


> A.pl: the main program, with one variable, e.g., $var, declared as
> global.
> #!/usr/bin/perl
> use strict;
> use warnings;
> use B;
> our $var = "hello";
> testB();


> B.pm: the module file, from which I want to access the $var variable
> in A.pl
> #!/usr/bin/perl
> package B;
> use strict;
> use warnings;
> require "A.pl"; ###########Actually I don't like this way, due
> to some problem
> sub testB{
> print "In B.pm, the variable is $var\n";
> ############Here I want the $var value in A.pl be accessible.
> }


> Is there a way doing this like in C language, we just need to declare
> it in B.pm, that the $var has been defined elsewhere, so it won't be
> checked during compile time but in runtime.


If you have A.pl

#!/usr/bin/perl
use strict;
use warnings;
use Bxx;

our $var = "hello";
Bxx::testB();

and Bxx.pm (I changed the name since there's already a packet called B)

#!/usr/bin/perl
package Bxx;
use strict;
use warnings;

sub testB{
print "In B.pm, the variable is $main::var\n";
}

1;

it simply works The 'main::' if front of the variable name
tells that it's defined in the main package. If 'A' would be
another package instead you would need 'use A;' at the start
and would have to qualify '$var' with 'A::' in front of it,
i.e. as '$A::var'.
Regards, Jens
--
\ Jens Thoms Toerring ___ http://www.velocityreviews.com/forums/(E-Mail Removed)
\__________________________ http://toerring.de
 
Reply With Quote
 
 
 
 
Michael Yang
Guest
Posts: n/a
 
      05-10-2007
On May 10, 5:30 pm, (E-Mail Removed) (Jens Thoms Toerring) wrote:
> Michael Yang <(E-Mail Removed)> wrote:
> > I want to access one global variable saved in the main script from
> > another one module. Here is what it looks like:
> > A.pl: the main program, with one variable, e.g., $var, declared as
> > global.
> > #!/usr/bin/perl
> > use strict;
> > use warnings;
> > use B;
> > our $var = "hello";
> > testB();
> > B.pm: the module file, from which I want to access the $var variable
> > in A.pl
> > #!/usr/bin/perl
> > package B;
> > use strict;
> > use warnings;
> > require "A.pl"; ###########Actually I don't like this way, due
> > to some problem
> > sub testB{
> > print "In B.pm, the variable is $var\n";
> > ############Here I want the $var value in A.pl be accessible.
> > }
> > Is there a way doing this like in C language, we just need to declare
> > it in B.pm, that the $var has been defined elsewhere, so it won't be
> > checked during compile time but in runtime.

>
> If you have A.pl
>
> #!/usr/bin/perl
> use strict;
> use warnings;
> use Bxx;
>
> our $var = "hello";
> Bxx::testB();
>
> and Bxx.pm (I changed the name since there's already a packet called B)
>
> #!/usr/bin/perl
> package Bxx;
> use strict;
> use warnings;
>
> sub testB{
> print "In B.pm, the variable is $main::var\n";
>
> }
>
> 1;
>
> it simply works The 'main::' if front of the variable name
> tells that it's defined in the main package. If 'A' would be
> another package instead you would need 'use A;' at the start
> and would have to qualify '$var' with 'A::' in front of it,
> i.e. as '$A::var'.
> Regards, Jens
> --
> \ Jens Thoms Toerring ___ (E-Mail Removed)
> \__________________________ http://toerring.de


Thanks for your information.It really helps.
But does it work with indirect invoking?
For example:
If I have one A.pl same as the one you gave, but in A.pl:
I invoked another script "C.pl", in which the testB is called.
A.pl:
#!/usr/bin/perl
use strict;
use warnings;
our $var = "hello";
my @output = `perl C.pl`;

C.pl:
#!/usr/bin/perl
use strict;
use warnings;
use Bxx;
Bxx::testB();

In this way, the $main:: refers to the script invoking the module's
functions, that is C.pl here rather than A.pl.
Is it due to the sub-process?

Thanks.

 
Reply With Quote
 
Jens Thoms Toerring
Guest
Posts: n/a
 
      05-10-2007
Michael Yang <(E-Mail Removed)> wrote:
> But does it work with indirect invoking?
> For example:
> If I have one A.pl same as the one you gave, but in A.pl:
> I invoked another script "C.pl", in which the testB is called.
> A.pl:
> #!/usr/bin/perl
> use strict;
> use warnings;
> our $var = "hello";
> my @output = `perl C.pl`;


> C.pl:
> #!/usr/bin/perl
> use strict;
> use warnings;
> use Bxx;
> Bxx::testB();


> In this way, the $main:: refers to the script invoking the module's
> functions, that is C.pl here rather than A.pl.
> Is it due to the sub-process?


This won't work because from A.pl you start a completely new
child process that knows nothing about any variables set in
the parent process that spawned it. In the example with the
original A.pl and Bxx.pm you had a single process and the
separation into A.pl and Bxx.pm is only something on source
code level, when the script get started, everything gets put
together. But if you start a program via backticks the ope-
rating system creates a process with its own memory and that
has no access to the memory of the parent process. Thus in
this case you somehow have to pass the value of '$var' to
the new process, the simplest method probably being via
command line arguments.
Regards, Jens
--
\ Jens Thoms Toerring ___ (E-Mail Removed)
\__________________________ http://toerring.de
 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      05-10-2007
On May 10, 11:29 am, Michael Yang <(E-Mail Removed)> wrote:
> On May 10, 5:30 pm, (E-Mail Removed) (Jens Thoms Toerring) wrote:
>
>
>
> > Michael Yang <(E-Mail Removed)> wrote:
> > > I want to access one global variable saved in the main script from
> > > another one module.


> > > Is there a way doing this like in C language, we just need to declare
> > > it in B.pm, that the $var has been defined elsewhere, so it won't be
> > > checked during compile time but in runtime.

>
> > it simply works The 'main::' if front of the variable name
> > tells that it's defined in the main package. If 'A' would be
> > another package instead you would need 'use A;' at the start
> > and would have to qualify '$var' with 'A::' in front of it,
> > i.e. as '$A::var'.


> Thanks for your information.It really helps.
> But does it work with indirect invoking?
> For example:
> If I have one A.pl same as the one you gave, but in A.pl:
> I invoked another script "C.pl", in which the testB is called.
> A.pl:
> #!/usr/bin/perl
> use strict;
> use warnings;
> our $var = "hello";
> my @output = `perl C.pl`;
>
> C.pl:
> #!/usr/bin/perl
> use strict;
> use warnings;
> use Bxx;
> Bxx::testB();
>
> In this way, the $main:: refers to the script invoking the module's
> functions, that is C.pl here rather than A.pl.
> Is it due to the sub-process?


Yes, a separate process has a completely separate memory space. This
is exactly the same as if one executable written in C called another -
they wouldn't share variables either.

There is a special variable %ENV that can carry information from
parent to child but not the other way.

I suspect you have an XY problem here. Can you explain what you are
trying to achieve? There is probably no reason to create a new perl
instance. Unless A.pl is a test harness for C.pl then C.pl should
probably just be another module.

 
Reply With Quote
 
Michael Yang
Guest
Posts: n/a
 
      05-10-2007
On May 10, 7:59 pm, Brian McCauley <(E-Mail Removed)> wrote:
> On May 10, 11:29 am, Michael Yang <(E-Mail Removed)> wrote:
>
>
>
>
>
> > On May 10, 5:30 pm, (E-Mail Removed) (Jens Thoms Toerring) wrote:

>
> > > Michael Yang <(E-Mail Removed)> wrote:
> > > > I want to access one global variable saved in the main script from
> > > > another one module.
> > > > Is there a way doing this like in C language, we just need to declare
> > > > it in B.pm, that the $var has been defined elsewhere, so it won't be
> > > > checked during compile time but in runtime.

>
> > > it simply works The 'main::' if front of the variable name
> > > tells that it's defined in the main package. If 'A' would be
> > > another package instead you would need 'use A;' at the start
> > > and would have to qualify '$var' with 'A::' in front of it,
> > > i.e. as '$A::var'.

> > Thanks for your information.It really helps.
> > But does it work with indirect invoking?
> > For example:
> > If I have one A.pl same as the one you gave, but in A.pl:
> > I invoked another script "C.pl", in which the testB is called.
> > A.pl:
> > #!/usr/bin/perl
> > use strict;
> > use warnings;
> > our $var = "hello";
> > my @output = `perl C.pl`;

>
> > C.pl:
> > #!/usr/bin/perl
> > use strict;
> > use warnings;
> > use Bxx;
> > Bxx::testB();

>
> > In this way, the $main:: refers to the script invoking the module's
> > functions, that is C.pl here rather than A.pl.
> > Is it due to the sub-process?

>
> Yes, a separate process has a completely separate memory space. This
> is exactly the same as if one executable written in C called another -
> they wouldn't share variables either.
>
> There is a special variable %ENV that can carry information from
> parent to child but not the other way.
>
> I suspect you have an XY problem here. Can you explain what you are
> trying to achieve? There is probably no reason to create a new perl
> instance. Unless A.pl is a test harness for C.pl then C.pl should
> probably just be another module.- Hide quoted text -
>
> - Show quoted text -


Thank you all!
I am designing a Test Harness for automation testing purpose.
The A.pl I mentioned is the entrance script of the harness, I call it
as main.pl here.
In main.pl, I need to call the invocant that is processing the jobs of
executing test cases, I call it Testrunner.pl here.
So it should be like this:

main.pl --------> Testrunner.pl ---------|---------------------
>case1.pm

($handler)
|---------------------->case2.pm

|---------------------->case3.pm

The $handler is a reference variable saved in the main.pl. I want it
be accessible from each case module, case1.pm, case2.pm, without
interference of Testrunner.pl. Because Testrunner.pl has been
finalized as the agent of running test jobs. I have to keep it
untouched.
What I only could do now is to modify the main.pl and case module
file. That's why I want to define the $handle as a global variable,
and want it be accessed from the module file.
How can I call Testrunner.pl from main.pl without spawning a separate
child process? If it is a possibility, in this way, the solution Jens
gave will work by $main::handler.

Thanks
Michael

 
Reply With Quote
 
Michael Yang
Guest
Posts: n/a
 
      05-10-2007
>
> main.pl --------> Testrunner.pl ---------|--------------------->case1.pm
>
> ($handler)
> |---------------------->case2.pm
>
> |---------------------->case3.pm
>


sorry for the ambiguity of this graph.

main.pl( $handler as its global variable) -------> Testrunner.pl -----
> (case1.pm, case2.pm, case3.pm)


Hope this would be clearer for understanding.

 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      05-10-2007
On May 10, 1:38 pm, Michael Yang <(E-Mail Removed)> wrote:
> On May 10, 7:59 pm, Brian McCauley <(E-Mail Removed)> wrote:


> > I suspect you have an XY problem here. Can you explain what you are
> > trying to achieve? There is probably no reason to create a new perl
> > instance. Unless A.pl is a test harness for C.pl then C.pl should
> > probably just be another module.
> >

> I am designing a Test Harness for automation testing purpose.
> The A.pl I mentioned is the entrance script of the harness, I call it
> as main.pl here.
> In main.pl, I need to call the invocant that is processing the jobs of
> executing test cases, I call it Testrunner.pl here.


> The $handler is a reference variable saved in the main.pl. I want it
> be accessible from each case module, case1.pm, case2.pm, without
> interference of Testrunner.pl. Because Testrunner.pl has been
> finalized as the agent of running test jobs. I have to keep it
> untouched.
> What I only could do now is to modify the main.pl and case module
> file. That's why I want to define the $handle as a global variable,
> and want it be accessed from the module file.


The way you are using the term "global variable" is not the way it is
usually used in most languages. (You haven't been using MUMPS have
you?) Usually a global variable is only global within a given process.

> How can I call Testrunner.pl from main.pl without spawning a separate
> child process?


You could do() it. However this would possibly give odd effects if you
try to call Testrunner.pl more than once from main.pl. I say /
possibly/ because if Testrunner.pl has written following best
practices then it would probably run OK (and all you'd need to do is
suppress the subroutine redefined warning).

> If it is a possibility, in this way, the solution Jens
> gave will work by $main::handler.


Actually if Testrunner.pl already "thinks" that it "owns" main:: then
you should use another namespace.

 
Reply With Quote
 
Michael Yang
Guest
Posts: n/a
 
      05-11-2007
On May 11, 1:07 am, Brian McCauley <(E-Mail Removed)> wrote:
> On May 10, 1:38 pm, Michael Yang <(E-Mail Removed)> wrote:
>
>
>
> > On May 10, 7:59 pm, Brian McCauley <(E-Mail Removed)> wrote:
> > > I suspect you have an XY problem here. Can you explain what you are
> > > trying to achieve? There is probably no reason to create a new perl
> > > instance. Unless A.pl is a test harness for C.pl then C.pl should
> > > probably just be another module.

>
> > I am designing a Test Harness for automation testing purpose.
> > The A.pl I mentioned is the entrance script of the harness, I call it
> > as main.pl here.
> > In main.pl, I need to call the invocant that is processing the jobs of
> > executing test cases, I call it Testrunner.pl here.
> > The $handler is a reference variable saved in the main.pl. I want it
> > be accessible from each case module, case1.pm, case2.pm, without
> > interference of Testrunner.pl. Because Testrunner.pl has been
> > finalized as the agent of running test jobs. I have to keep it
> > untouched.
> > What I only could do now is to modify the main.pl and case module
> > file. That's why I want to define the $handle as a global variable,
> > and want it be accessed from the module file.

>
> The way you are using the term "global variable" is not the way it is
> usually used in most languages. (You haven't been using MUMPS have
> you?) Usually a global variable is only global within a given process.
>
> > How can I call Testrunner.pl from main.pl without spawning a separate
> > child process?

>
> You could do() it. However this would possibly give odd effects if you
> try to call Testrunner.pl more than once from main.pl. I say /
> possibly/ because if Testrunner.pl has written following best
> practices then it would probably run OK (and all you'd need to do is
> suppress the subroutine redefined warning).
>
> > If it is a possibility, in this way, the solution Jens
> > gave will work by $main::handler.

>
> Actually if Testrunner.pl already "thinks" that it "owns" main:: then
> you should use another namespace.


I am thinking about using 'require' to do this:
@ARGV = ();
require 'Testrunner.pl';

In this way, the variable defined in the main script is in the same
context as the Testrunner.pl, and could be accessed from the module
file.
But I found it slows the harness greatly, the performance is lowered.
How to leaverage on this?

 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      05-11-2007
On 11 May, 06:03, Michael Yang <(E-Mail Removed)> wrote:
> On May 11, 1:07 am, Brian McCauley <(E-Mail Removed)> wrote:
> > On May 10, 1:38 pm, Michael Yang <(E-Mail Removed)> wrote:


> > > How can I call Testrunner.pl from main.pl without spawning a separate
> > > child process?


> > You could do() it. However this would possibly give odd effects if you
> > try to call Testrunner.pl more than once from main.pl.


> I am thinking about using 'require' to do this:
> @ARGV = ();
> require 'Testrunner.pl';
>
> In this way, the variable defined in the main script is in the same
> context as the Testrunner.pl, and could be accessed from the module
> file.


Yes that's what I said. Well I said do() not require(). But the only
difference in this conext is that main.pl _cannot_ run Testrunner.pl
more than once.

> But I found it slows the harness greatly, the performance is lowered.


That seems highly counter-intuative. I would expect it to be a little
faster as you are only loading perl once.

How are you observing this? Is it possible that it's not the tests
that are running slowly but rather something like an output buffering
issue?

> How to leaverage on this?


Well the bunderbus thing would be to make a copy of the whole thing,
main.pl, Testrunner.pl and at least one test case and check you still
see the difference. Then cut bits out progressively checking at each
stage that you still see the difference.

Eventually you'll have a minimal but complete test case to illustrate
the behaviour. If but this time you've not spotted what's happening
then you should post the three files (which by now should be <20 lines
each).

 
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
Issue in executing more than one perl script from Single perl script nilesh.sonawane@gmail.com Perl Misc 3 11-01-2007 06:19 PM
Initialize global variable before any other global variables jubelbrus C++ 5 07-20-2007 06:38 PM
501 PIX "deny any any" "allow any any" Any Anybody? Networking Student Cisco 4 11-16-2006 10:40 PM
Any one know how to set an alias in the perl, and use it after the perl script end Lim kiang Leng Perl Misc 3 07-17-2004 11:11 PM
Perl Help - Windows Perl script accessing a Unix perl Script dpackwood Perl 3 09-30-2003 02:56 AM



Advertisments