Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

I just want to include another file

by Cap'n Steve (Friar)
on Sep 14, 2004 at 05:08 UTC ( [id://390741]=perlquestion: print w/replies, xml ) Need Help??

Cap'n Steve has asked for the wisdom of the Perl Monks concerning the following question:

Is there any simple way to do this? I have several cgi scripts that use a common set of modules, plus several of the same variables and subroutines. It'd be much easier to put this in a seperate file, instead of having several copies of the same code. I don't want to write a module, and I've been trying to use require(), but dealing with the different namespaces is giving me a headache, especially trying to share the object for CGI.pm. Am I missing some good reason why there isn't a simple include() function in Perl?

Replies are listed 'Best First'.
Re: I just want to include another file
by CountZero (Bishop) on Sep 14, 2004 at 05:37 UTC
    Did you consider using do?

    From the perldocs:

    do EXPR

    Uses the value of EXPR as a filename and executes the contents of the file as a Perl script. Its primary use is to include subroutines from a Perl subroutine library.

    do 'stat.pl';

    is just like

    scalar eval `cat stat.pl`;

    except that it's more efficient and concise, keeps track of the current filename for error messages, searches the @INC libraries, and updates %INC if the file is found. It also differs in that code evaluated with do FILENAME cannot see lexicals in the enclosing scope; eval STRING does. It's the same, however, in that it does reparse the file every time you call it, so you probably don't want to do this inside a loop.

    If do cannot read the file, it returns undef and sets $! to the error. If do can read the file but cannot compile it, it returns undef and sets an error message in $@. If the file is successfully compiled, do returns the value of the last expression evaluated.

    Note that inclusion of library modules is better done with the use and require operators, which also do automatic error checking and raise an exception if there's a problem.

    You might like to use do to read in a program configuration file. Manual error checking can be done this way:

    # read in config files: system first, then user for $file ('/share/prog/defaults.rc', "$ENV{HOME}/.someprogrc") { unless ($return = do $file) { warn "couldn't parse $file: $@" if $@; warn "couldn't do $file: $!" unless defined $return; warn "couldn't run $file" unless $return; } }

    Update: changed formatting to allow Monks with other CSS-stylesheets to see this correctly (thanks davido for reminding me)

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

      Thank you! I knew it had to be something simple, but I couldn't find it for the life of me.
        I have the funny feeling when you talk about dealing with different namespaces, you really mean different scopes, and that "code evaluated with do FILENAME cannot see lexicals in the enclosing scope" bit will defeat you. Which means either going the route of reading the file in and eval'ing it, or not trying to share lexicals with the included code.
Re: I just want to include another file
by thospel (Hermit) on Sep 14, 2004 at 11:31 UTC
    Notice that you don't HAVE to use namespaces with require or use. All of that stuff is just conventions (though the import that can be implicit in use will be to what the package name seems to be). And it's usually nicer to use "use" than "require" or "do" even for "include", since you will see any errors before runtime of the main program gets there, subs in there are already known to the compiler when it's compiling your main code, and there is some implicit checking that the "included" code didn't crash.

    So it's perfectly ok to e.g. have a Foo.pm file containing:

    # Warnings, strict and our aren't needed if you don't # want to bother. I Just like to have them use strict; use warnings; our $c = 5; sub foo { print $c; } # Next line is the only thing that's different from # what you'd have if you were going to use "do" # A filed being required/used should return something true 1;

    And then use that as:

    use Foo(); use strict; # you couldn't call foo without () under use strict # if you had used "require" or "do" foo; our $c; print $c;

    Notice the () in use Foo(). It avoids a call to import, though supposedly if you use this you won't have a Foo package and there will be no import there, so you could leave them out too.

    Having said that, it's still often a good idea to make commonly used code into a real module. You can use the Exporter if you want subs and variables in there available unqualified in your main code. It's only a few trivial lines more:

    package Foo; # This line is new use strict; use warnings; use base qw(Exporter); # This line is new our @EXPORT_OK =qw($c foo); # This line is new, stuff the caller MAY +import to use it unqualified our $c = 5; sub foo { print $c; } 1;
    And on use you have to say which of the exported things you'd like to use:
    # Next line is different, explicitely say we want to use foo unqualifi +ed (without Foo::) use Foo qw(foo); use strict; foo; # We could also have listed $c in the import list and then use plain $ +c # But let's instead show you can still access it by qualifying print $Foo::c;
Re: I just want to include another file
by hmerrill (Friar) on Sep 14, 2004 at 13:18 UTC
    IMHO, that's exactly what modules are for - to contain functions or code commonly used. Bite the bullet and take the time to learn how to write modules. They're really not that tough :-)

    Then once you've got your modules, you can put them in one place so that all your apps can get to them by doing something like this:

    use lib '/path/to/your/module/directory'; use your_module1; use your_module2;
    HTH.
      It just seems silly to me to clutter the code with extra modules and deal with exporting when I'll want the same symbols every time. I'll try use() again, I think having to declare variables in both files was what was messing me up. It seems like it should work just by using our() in the included file though.
        I don't have code at my fingertips to show you, but you don't have to declare variables in both files. If the export is done properly in the module, you can simply refer to the variables in the code that does the "use". I hope I'm not oversimplying here - it's been a while since I've done this, and I'm not actively using Perl now.

        I also think when I did create modules that I used a simplified approach of not doing "export"s at all. The "use" still worked the same, but to refer to variables in the module I had to use the module name, something like this:

        use lib '/path/to/my/module/directory'; use MyMod; print "MyMod var1 value is $MyMod::var1\n";
        Again, not sure if this is exactly right, but it should be close. I liked this approach because looking at the code you can always tell *where* a variable comes from - you don't need to go hunting around for it if you see that it hasn't been declared in the current module. You *are* using warnings(-w), strict, and declaring all your variables with "my", right??

        HTH.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://390741]
Approved by graff
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (3)
As of 2024-04-21 02:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found