Passing vars to a "require"d script

Discussion in 'Perl Misc' started by Bigus, Jul 29, 2005.

  1. Bigus

    Bigus Guest

    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
     
    Bigus, Jul 29, 2005
    #1
    1. Advertising

  2. 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
     
    it_says_BALLS_on_your forehead, Jul 29, 2005
    #2
    1. Advertising

  3. Bigus

    Paul Lalli Guest

    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
     
    Paul Lalli, Jul 29, 2005
    #3
  4. Bigus

    Guest

    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().
     
    , Jul 29, 2005
    #4
  5. Bigus <> 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
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Jul 29, 2005
    #5
  6. "Bigus" <> wrote in message
    news:dcdi7n$i4b$...
    > 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
     
    Klaus Eichner, Jul 29, 2005
    #6
  7. Bigus

    Guest

    Bigus wrote:
    > [..]
    > > 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'.
     
    , Jul 30, 2005
    #7
  8. "Bigus" <> wrote in message
    news:42eb3dea$0$91525$...
    >
    > "Klaus Eichner" <> wrote in message
    > news:42ea5707$0$5043$...
    > > You can always define your own variables with "our" to pass values,

    like:
    > > our @param = ('?', '123');
    > >
    > > Then, inside "/admin/scripts/live/otherscript.pl"
    > > our @param;

    >
    > 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
     
    Klaus Eichner, Jul 30, 2005
    #8
  9. Bigus

    Paul Lalli Guest

    Bigus wrote:
    > "Paul Lalli" <> wrote in message
    > news:...
    > > 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().


    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
     
    Paul Lalli, Jul 30, 2005
    #9
  10. Bigus <> wrote:
    > "Tad McClellan" <> wrote in message
    > news:...
    >> Bigus <> wrote:
    >>
    >>> If I call a separate script from within a CGI script using "require",


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



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


    >>> 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?

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

    ??


    >> 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!



    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
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Jul 30, 2005
    #10
  11. Paul Lalli <> 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
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Jul 31, 2005
    #11
  12. Bigus

    Paul Lalli Guest

    Tad McClellan wrote:
    > Paul Lalli <> 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.


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

    Paul Lalli
     
    Paul Lalli, Jul 31, 2005
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jon

    app vars and cache vars

    Jon, Dec 14, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    427
  2. brad
    Replies:
    1
    Views:
    278
    Will Maier
    Aug 7, 2007
  3. Linuxguy123
    Replies:
    7
    Views:
    733
    Paddy O'Loughlin
    Feb 20, 2009
  4. Replies:
    0
    Views:
    290
  5. caccolangrifata
    Replies:
    18
    Views:
    430
    Chris Torek
    Jul 22, 2011
Loading...

Share This Page