For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > July 2005 > Passing vars to a "require"d script









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Passing vars to a "require"d script
Bigus

2005-07-29, 5:03 pm

If I call a separate script from within a CGI script using "require", is
there any (simple) way of passing a variable to it?

I've tried:

require "/admin/scripts/live/otherscript.pl?123"

and trying to pick it up via @ARGV but it comes up with an error saying it
can't find the script. In other words it seems to treat the "?123" as part
of the file name.

Bigus


it_says_BALLS_on_your forehead

2005-07-29, 5:03 pm

usually the files that i require only have subs in them--they don't DO
anything. what are you trying to do exactly?


Bigus wrote:
> If I call a separate script from within a CGI script using "require", is
> there any (simple) way of passing a variable to it?
>
> I've tried:
>
> require "/admin/scripts/live/otherscript.pl?123"
>
> and trying to pick it up via @ARGV but it comes up with an error saying it
> can't find the script. In other words it seems to treat the "?123" as part
> of the file name.
>
> Bigus


Klaus Eichner

2005-07-29, 5:03 pm

"Bigus" <someone@somewhere.com> wrote in message
news:dcdi7n$i4b$1@blackmamba.itd.rl.ac.uk...
> If I call a separate script from within a CGI script using "require", is
> there any (simple) way of passing a variable to it?
>
> I've tried:
>
> require "/admin/scripts/live/otherscript.pl?123"
>
> and trying to pick it up via @ARGV but it comes up with an error saying it
> can't find the script. In other words it seems to treat the "?123" as part
> of the file name.


You can always define your own variables with "our" to pass values, like:

our @param = ('?', '123');
require "/admin/scripts/live/otherscript.pl";

Then, inside "/admin/scripts/live/otherscript.pl", you repeat the "our
@param", but without the "= ('?', '123')". This allows you to access the
variables inside the "otherscript.pl":

our @param;
print "\@param = (@param)\n";

--
Klaus


Paul Lalli

2005-07-29, 5:03 pm


Bigus wrote:
> If I call a separate script from within a CGI script using "require", is
> there any (simple) way of passing a variable to it?
>
> I've tried:
>
> require "/admin/scripts/live/otherscript.pl?123"
>
> and trying to pick it up via @ARGV but it comes up with an error saying it
> can't find the script. In other words it seems to treat the "?123" as part
> of the file name.


It is part of the filename. What makes you think it wouldn't be?

If you want your required file to get a different @ARGV, give it a
different @ARGV:

###main.pl:###
#!/usr/bin/perl

use strict;
use warnings;

print "In main: \@ARGV = @ARGV\n";

{
local @ARGV = qw/other script/;
require "req.pl";
}

print "Back in main, \@ARGV = @ARGV\n";

__END__


###req.pl:###
print "In required file, \@ARGV = @ARGV\n";



OUTPUT:
../main.pl one two three
In main: @ARGV = one two three
In required file, @ARGV = other script
Back in main, @ARGV = one two three

nobull@mail.com

2005-07-29, 5:03 pm


Bigus wrote:
> If I call a separate script from within a CGI script using "require", is
> there any (simple) way of passing a variable to it?
>
> I've tried:
>
> require "/admin/scripts/live/otherscript.pl?123"


Repeat after me...

Perl is not CGI or HTTP
HTTP and CGI are not Perl
Perl is not CGI or HTTP
HTTP and CGI are not Perl
Perl is not CGI or HTTP
HTTP and CGI are not Perl
Perl is not CGI or HTTP
HTTP and CGI are not Perl
Perl is not CGI or HTTP
HTTP and CGI are not Perl

OK.

> and trying to pick it up via @ARGV but it comes up with an error saying it
> can't find the script. In other words it seems to treat the "?123" as part
> of the file name.


What would make to suspect it might to otherwise?

When you require a Perl source file it is compiled and executed in the
current Perl interpreter. As such any package variables that you
defined before the require() will be accessible to the code within the
required file.

However I suspect you've completely missed the point of require().

Tad McClellan

2005-07-29, 5:03 pm

Bigus <someone@somewhere.com> wrote:

> If I call a separate script from within a CGI script using "require",



Then we have entered the Twilight Zone, as what you describe
is impossible. :-)

require does not "call" a "separate" program, it "includes" some
code in the _current_ program.

system(), exec(), backticks or a pipe-open is how truly "separate"
programs are called from within Perl.


> is
> there any (simple) way of passing a variable to it?



Yes, but we should first address why you think that you need to do that.

Why do you feel that you need to pass an argument to a require'd file?

Why not simply rewrite the .pl function to take a proper argument,
and then supply the argument in the main program's function call?


> I've tried:
>
> require "/admin/scripts/live/otherscript.pl?123"



That indicates that you have an improper mental model of how things
work. Correcting that will go a long way toward avoiding future confusions.

URL-like methods have no connection whatsoever to Perl, so your thinking
that that question-mark thing would work indicates your model problem.


> and trying to pick it up via @ARGV but it comes up with an error saying it
> can't find the script. In other words it seems to treat the "?123" as part
> of the file name.



That is exactly what it is supposed to do.

If you really really need to "pass" variables (I doubt that you do),
you can do it thus:

--------------------------
use warnings; # foo.pl
use strict;
our $foo;
sub func1 { print $foo }
1;
--------------------------
#!/usr/bin/perl
use warnings; # main program
use strict;

our $foo = 'foobar';
require 'foo.pl';

func1();
--------------------------



--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
Bigus

2005-07-30, 4:00 am


"Tad McClellan" <tadmc@augustmail.com> wrote in message
news:slrndeknir.6b6.tadmc@magna.augustmail.com...
> Bigus <someone@somewhere.com> wrote:
>
>
>
> Then we have entered the Twilight Zone, as what you describe
> is impossible. :-)
>
> require does not "call" a "separate" program, it "includes" some
> code in the _current_ program.
>
> system(), exec(), backticks or a pipe-open is how truly "separate"
> programs are called from within Perl.


yes, that's what I thought, except I've always managed to get require to do
the job I want in the cirumstances I've used it until now. I did actually
try using backticks (though it's a pain having to convert all the forward
slashes in paths into double back slashes (Windows)) however then the
require'd script didn't seem to pull in the form data, which I assumed was
because a system call doesn't maintain the CGI context?

>
>
> Yes, but we should first address why you think that you need to do that.
>
> Why do you feel that you need to pass an argument to a require'd file?


Basically, I've got a set of server administration tools. Each tool is a
separate .pl script (along with a html control form) that is knitted
together into one web interface by a handler CGI (admin.cgi) script.
admin.cgi deals with the login and generates a session ticket which I want
to pass to the tool .pl that I'm requiring.

> Why not simply rewrite the .pl function to take a proper argument,
> and then supply the argument in the main program's function call?


Well, yeah, I could reengineer everything but that involves changing a fair
few lines.

>
>
> That indicates that you have an improper mental model of how things
> work. Correcting that will go a long way toward avoiding future
> confusions.


yeah, you're probably quite correct ;) actually, the admin.cgi I mentioned
also has an associated admin.pl which is purely a library of subs that I
call from admin.cgi, and for that matter some of the tool .pl's, so that is
presumably more like a correct model of usage?

> URL-like methods have no connection whatsoever to Perl, so your thinking
> that that question-mark thing would work indicates your model problem.


I didn't think that would work, but it was the only thing I could think of
trying. I found an article on "our()" as you mention below, but I didn't
manage to get it work (largely because the article didn't mention you have
to also use our() in the receiving script aswell!).

[..]
> If you really really need to "pass" variables (I doubt that you do),
> you can do it thus:
>
> --------------------------
> use warnings; # foo.pl
> use strict;
> our $foo;
> sub func1 { print $foo }
> 1;
> --------------------------
> #!/usr/bin/perl
> use warnings; # main program
> use strict;
>
> our $foo = 'foobar';
> require 'foo.pl';
>
> func1();
> --------------------------


thanks.. I'll use that method for now!

Bigus


Bigus

2005-07-30, 4:00 am


"Klaus Eichner" <klaus_gb@yahoo.com> wrote in message
news:42ea5707$0$5043$636a15ce@news.free.fr...
> "Bigus" <someone@somewhere.com> wrote in message
> news:dcdi7n$i4b$1@blackmamba.itd.rl.ac.uk...
>
> You can always define your own variables with "our" to pass values, like:
>
> our @param = ('?', '123');
> require "/admin/scripts/live/otherscript.pl";
>
> Then, inside "/admin/scripts/live/otherscript.pl", you repeat the "our
> @param", but without the "= ('?', '123')". This allows you to access the
> variables inside the "otherscript.pl":
>
> our @param;
> print "\@param = (@param)\n";


thanks, that works nicely :)

I had read an article on our() but it didn't mention you had to use our()
again in "receiving" script. I thought it must make it global to everything.

Bigus


Bigus

2005-07-30, 4:00 am

[..]
> When you require a Perl source file it is compiled and executed in the
> current Perl interpreter. As such any package variables that you
> defined before the require() will be accessible to the code within the
> required file.


So, if I have a script called admin.cgi and in that script I do the
usual....

use CGI;
my $q = new CGI;
my %fd = $q->Vars;

.....to get the form data into a hash.

Then I "require" tool.pl and inside a subroutine in tool.pl I will be able
to access all the values in %fd?

If so then I need to get back to the testing board, because one of the ways
I had tried to get a variable passed to the require'd script was by creating
a new key/value in the %fd hash, thinking it was in some global namespace
that could be accessed by require'd scripts aswell. However, it didn't work.
So if it should have done then I evidently must have messed something up!

Bigus


Bigus

2005-07-30, 4:00 am


"Paul Lalli" <mritty@gmail.com> wrote in message
news:1122654892.530541.287900@g43g2000cwa.googlegroups.com...
[..]
> It is part of the filename. What makes you think it wouldn't be?


well, it I was just clutching at straws for sometihng that might work and
not ask any questions if it did ;)

> If you want your required file to get a different @ARGV, give it a
> different @ARGV:
>
> ###main.pl:###
> #!/usr/bin/perl
>
> use strict;
> use warnings;
>
> print "In main: \@ARGV = @ARGV\n";
>
> {
> local @ARGV = qw/other script/;
> require "req.pl";
> }
>
> print "Back in main, \@ARGV = @ARGV\n";
>
> __END__
>
>
> ###req.pl:###
> print "In required file, \@ARGV = @ARGV\n";


thanks, that's a different way of doing it than our().

Bigus


Bigus

2005-07-30, 4:00 am


"it_says_BALLS_on_your forehead" <simon.chao@fmr.com> wrote in message
news:1122652881.213755.220480@g47g2000cwa.googlegroups.com...
> usually the files that i require only have subs in them--they don't DO
> anything. what are you trying to do exactly?


well, I have some scripts like this:

|-----------|
| admin.cgi |
|-----------|
|
|------>-----|------->------|
| | |
|----------| |----------| |----------|
| admin.pl | | tool1.pl | | tool2.pl | etc
|----------| |----------| |----------|
| | |
|------<-----|-------<------|

(I hope you are reading this in a monospaced font otherwise that will look a
little jumbled ;)

admin.cgi handles all the http requests and calls, via require, any of the
other scripts. admin.pl just has one subroutine in it that generates the
common web interface HTML and feeds it back to the user. the individual
tool<n>.pl files can also call that sub in admin.pl.

In this case, I have admin.cgi generating a session ticket after a
successful user login.. it calls the sub in admin.pl, passing the session
ticket as it does so. admin.pl then works out which tool is the first in the
menu and calls tool1.pl**, for example. tool1.pl gets together it's own HTML
(ie: the control form) and calls the sub in admin.pl, passing it's HTML to
be included into the main interface HTML.

** this is where I need to pass the session ticket to tool1.pl, but
tool1.pl's code isn't all in a subroutine and so I couldn't pass the ticket
in the normal way. I guess I should rejig everything to only have subs
inside required files but that rquires changing a fair few lines of code and
program logic, whereas I thought a quick fix would be passing the ticket in
some other way.

Bigus


nobull@mail.com

2005-07-30, 9:01 am


Bigus wrote:
> [..]
>
> So, if I have a script called admin.cgi and in that script I do the
> usual....
>
> use CGI;
> my $q = new CGI;
> my %fd = $q->Vars;
>
> ....to get the form data into a hash.
>
> Then I "require" tool.pl and inside a subroutine in tool.pl I will be able
> to access all the values in %fd?


No, I said _package_ variables.

If you changed the 'my' in the declaration of %fd to 'our' and also put
a similar declaration in tool.pl then yes code in tools.pl would be
sharing the same %fd. That's the point of the names 'my' and 'our'.
My something is mine alone. Our something is mine and also is shared
with others.

Note: if you omit 'use strict' then you can omit the 'our' declaration
but that would be a very bad idea.

> If so then I need to get back to the testing board, because one of the ways
> I had tried to get a variable passed to the require'd script was by creating
> a new key/value in the %fd hash, thinking it was in some global namespace
> that could be accessed by require'd scripts aswell. However, it didn't work.
> So if it should have done then I evidently must have messed something up!


You still have the wrong mental model. You should not think about the
required file as a 'script'.

Klaus Eichner

2005-07-30, 5:00 pm

"Bigus" <personage@myabode.com> wrote in message
news:42eb3dea$0$91525$ed2e19e4@ptn-nntp-reader04.plus.net...
>
> "Klaus Eichner" <klaus_gb@yahoo.com> wrote in message
> news:42ea5707$0$5043$636a15ce@news.free.fr...
like:[color=darkred]
>
> thanks, that works nicely :)
>
> I had read an article on our() but it didn't mention you had to use our()
> again in "receiving" script. I thought it must make it global to

everything.
>
> Bigus


I can understand what you are saying.
It took me a long time to realise that "my()" and "our()" -- although
similar in a sense that they both declare variables within the enclosing
block, file or eval -- are working rather differently.

"my()" creates a new variable every time it is called, but "our()" doesn't
really do anything, other than allowing access to a global variable. (you
don't even need "our()" at all if you don't "use strict" in your script
! ) -- in particular: a simple "our()" does not make a global variable, it
is the subsequent assignment which makes the global variable.

Therefore, multiple "our()'s" of the same variable in different blocks (or
files, for that matter) really refer to one unique global variable.

--
Klaus


Paul Lalli

2005-07-30, 5:00 pm

Bigus wrote:
> "Paul Lalli" <mritty@gmail.com> wrote in message
> news:1122654892.530541.287900@g43g2000cwa.googlegroups.com...
>
> thanks, that's a different way of doing it than our().


Uh. No it's not. You seem to be as to what our() and local()
(and possibly my()) do.

Neither our() nor local() declare any new variables. our() allows
access to a package variable without fully qualifying it for the
duration of our()'s lexical scope. (Note that this means if you're not
using strict, our() has no effect of any kind). `our $foo;` Simply
allows you to say "$foo" to mean "$main::foo".

local() provides a package variable with a temporary variable for the
duration of the local() statement's lexical scope (and any subroutines
called within that scope). It does not declare any variable, and it
is not sufficient to overcome strict's restrictions.

The only reason I was able to say local @ARGV; above without a prevous
our @ARGV is that @main::ARGV is "special". The sequence of characters
'@ARGV' always means '@main::ARGV' (unless you've declared a lexical
variable `my @ARGV;` -- don't do that).

If we were using any other package variable, like @main::args, we would
have to fully qualify the variable or use our().

#valid:
our @args = qw/stuff/;
{
local @args = qw/foo bar/;
require 'req.pl';
}

#valid:
@main::args = qw/stuff/;
{
local @main::args = qw/foo bar/;
require 'req.pl';
}

#NOT valid:
{
local @args = qw/foo bar/;
require 'req.pl';
}


Hope this makes sense
Paul Lalli

Tad McClellan

2005-07-30, 10:00 pm

Bigus <personage@myabode.com> wrote:
> "Tad McClellan" <tadmc@augustmail.com> wrote in message
> news:slrndeknir.6b6.tadmc@magna.augustmail.com...
[color=darkred]

[color=darkred]
> then the
> require'd script didn't seem to pull in the form data, which I assumed was
> because a system call doesn't maintain the CGI context?



I dunno what you mean by "CGI context".

They have access to the same environment that the calling program
had when it called the external program.


>
> Basically, I've got a set of server administration tools. Each tool is a
> separate .pl script (along with a html control form) that is knitted
> together into one web interface by a handler CGI (admin.cgi) script.
> admin.cgi deals with the login and generates a session ticket which I want
> to pass to the tool .pl that I'm requiring.
>
>
> Well, yeah, I could reengineer everything but that involves changing a fair
> few lines.



That is the price you pay when you proceed with a poor design.

Most of these issues would not have come up if you had designed
your code with appropriate modularity in the first place.

(Are you perhaps, new to programming in general?)

Put subroutines (not code) in libraries (and a Real Module is much
better yet) and pass arguments from the main program.

Live and learn. :-)


> also has an associated admin.pl which is purely a library of subs that I
> call from admin.cgi, and for that matter some of the tool .pl's, so that is
> presumably more like a correct model of usage?



Yes, subs in libraries, main code in main code.


> I found an article on "our()"



Was it:

"Coping with Scoping":

http://perl.plover.com/FAQs/Namespaces.html

??


>
> thanks.. I'll use that method for now!



Ugh. You will re-live all the programming headaches of
the 60s and 70s then.


Here is a "proper" redesign of what I posted (untested):

use warnings; # foo.pl
use strict;
sub func1 { print $_[0] }
1;

and

#!/usr/bin/perl
use warnings; # main program
use strict;
require 'foo.pl';

my $foo = 'foobar';
func1($foo);


Look Ma! Low coupling, no globals!

That wasn't very hard...


--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
Tad McClellan

2005-07-31, 9:00 am

Paul Lalli <mritty@gmail.com> wrote:


> local() provides a package variable with a temporary variable for the
> duration of the local() statement's lexical scope



It helps to remember that local() doe NOT make a temporary variable!

local() makes a temporary *value* for a variable.

What is "local" is not the variable, but the variable's value.


--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
Paul Lalli

2005-07-31, 5:17 pm

Tad McClellan wrote:
> Paul Lalli <mritty@gmail.com> wrote:
>
>
>
>
> It helps to remember that local() doe NOT make a temporary variable!
>
> local() makes a temporary *value* for a variable.
>
> What is "local" is not the variable, but the variable's value.


Gah. That was a typo on my part. Thanks for catching that, Tad.

Paul Lalli

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2009 codecomments.com