Passing vars to a "require"d script

B

Bigus

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
 
I

it_says_BALLS_on_your forehead

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

Paul Lalli

Bigus said:
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
 
N

nobull

Bigus said:
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().
 
T

Tad McClellan

Bigus said:
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();
 
K

Klaus Eichner

Bigus said:
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";
 
N

nobull

Bigus said:
[..]
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?

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'.
 
K

Klaus Eichner

Bigus said:
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.
 
P

Paul Lalli

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

Uh. No it's not. You seem to be confused 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
 
T

Tad McClellan

Bigus said:
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...
 
T

Tad McClellan

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.
 
P

Paul Lalli

Tad said:
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
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top