kiat has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I'm trying out with a script that calls module which stores a hash of country information. The following is my sample code:
#script.pl #!/usr/local/bin/perl #use strict; use CGI qw(:standard); eval { ($0 =~ m,(.*)/[^/]+,) && unshift (@INC, "$1"); require 5.001; require "module.pm"; }; if ($@) { die("Error including libraries: $@\n"); } msg(); sub msg { print "Content-type: text/html\n\n"; print "<html>\n"; print "<head>\n"; print "<title>Country</title>\n"; print "</head>\n"; print "<body bgcolor=\"#FFFFFF\" text=\"#000000\">"; print "$country{'af'}<br>\n"; print "</body>\n</html>\n"; } # module.pm # module.pm %country = ( af => 'afghanistan', ao => 'angola', ar => 'argentina', at => 'austria', au => 'australia', bd => 'bangladesh', be => 'belgium', bg => 'bulgaria', );
When I enable 'strict', the code doesn't work. I tried to declare the hash %country with 'my' but it doesn't help. I figured it's something to do with Exporter but I'm not quite sure how that's done.

Please advise and thanks in anticipation =)

Replies are listed 'Best First'.
(jeffa) Re: Problems with using strict
by jeffa (Bishop) on Apr 19, 2003 at 14:36 UTC
    The way in which you are loading module.pm is most likely deprecated. Besides, you don't even show us what that module is/does. I recommond you ditch that code and start over with something like:
    use strict; use warnings; use CGI::Pretty qw(:standard); use Geography::Countries; print header, start_html('Country'), scalar country('AF'), end_html, ;
    You more than likely have CGI installed, but you more than likely do not have Geography::Countries already installed. Grab it. Use the CPAN. Make your life easier. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Thanks, jeffa! What is the correct way to include a module and how do I fix my code above assuming I need to include a self-written module?
        No problem. I like to first add the path where the module lies to @INC rather than assume the module will always be in the same directory as the executing script. Something like:
        use lib '/path/to/my/module'; use module;
        require is not deprecated, but i use use 99.99% of the time. Follow those links or read about those two pragmas with:
        
        perldoc -f use
        perldoc -f require
        
        If you want to install Geography::Countries, you should read A Guide to Installing Modules.

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        

        A couple of ways...

        • Put the module in the directory where the script runs
        • Add use lib '/path/to/my/modules' before using any of your modules
        • Update: Set the environment variable PERLLIB or PERL5LIB to the location of your modules
        90% of every Perl application is already written.
        dragonchild
Re: Problems with using strict
by pfaut (Priest) on Apr 19, 2003 at 14:31 UTC

    I'm guessing you didn't include any error messages in your post because this is a CGI script and you don't know how to find them. Here's some tips for debugging CGI errors.

    • Use perl -c <filename> after any changes. This tells perl to load up your script and parse it but not execute it ('use' statements and BEGIN blocks will be executed). If there are any syntax errors in your script, they should be found here. Since you're getting an error when trying to use strict, this should tell you more about the problem.
    • Execute the code from the shell. This is real easy if your script doesn't accept form input or look at web server provided environment variables but even if it does that's easy enough to provide. Any expected environment variables can be set to appropriate values before executing the script. Form variables can be provided on the command line as field=value pairs (you are using CGI.pm to parse your form input, right?).
    • If you get past these steps and still have problems executing your code from a browser, look for your web server's error log file. Any output to your application's STDERR should be written to that file. As an alternative, add the following to the top of your script to have your own error log:
      BEGIN { open STDERR,">>my_script_errors.log" or die "Unable to open errorlog"; }

      Make sure that whatever account your web server uses to execute scripts has write access to the file and directory you specify.

    90% of every Perl application is already written.
    dragonchild
Re: Problems with using strict
by Aristotle (Chancellor) on Apr 19, 2003 at 15:21 UTC
    You need to tell strict that %country is a package variable.
    use vars qw(%country);
    That will create a global variable %main::country which can be referred to from other scopes (such as a different file) by name. Using my in module.pm won't work, because it scopes the variable locally to that file, ie it will vanish as soon as execution returns from the file. Another alternative I'd prefer in this case is to create a hashref in the included file:
    +{ af => 'afghanistan', ao => 'angola', ar => 'argentina', at => 'austria', au => 'australia', bd => 'bangladesh', be => 'belgium', bg => 'bulgaria', };
    and then use do on it:
    my $country = do "countries.pl"; die "Error loading country data: $@\n" if $@;
    Now a reference to the constructed hash is stored in $country:
    print "$country->{af}\n";

    (Note that do does an implicit eval.)

    Update: that's my $country = do ..; of course.

    Makeshifts last the longest.

Re: Problems with using strict
by pfaut (Priest) on Apr 19, 2003 at 15:23 UTC

    Get rid of the eval block and replace it with use Country. Other posts in this thread will show you how to get the location of your module into @INC so it can be loaded with a simple 'use'. Then put the following into Country.pm.

    package Country; use strict; use base 'Exporter'; our @EXPORT = qw(%country); our %country = ( af => 'afghanistan', ao => 'angola', ar => 'argentina', at => 'austria', au => 'australia', bd => 'bangladesh', be => 'belgium', bg => 'bulgaria', ); 1;

    This should get rid of your errors when using strict.

    See perldoc Exporter for help on using EXPORT.

    90% of every Perl application is already written.
    dragonchild