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

I have the following call in my script.
script_stats($runtime, $start);

The script is run from /Perl and the module is located in /Perl/Modules Here the entire (very small) module.

#!/usr/bin/perl use warnings; use strict; use DBD::mysql; package ScriptUpdate; our @ISA = qw(Exporter); our @EXPORT = qw(script_stats); # symbols to be exported by default + (space-separated) our $VERSION = 1.10; sub script_stats { my ($runtime, $rundate) = @_; chomp(my $filename = $0); chomp(my $currentuser=`whoami`); #Holds modified date for file my $mtime = stat($filename)->mtime; my $dbh = DBI->connect("DBI:mysql:database=ts_tool_track:host=xxxx +",'xxxx','xxxx') || die "$DBI::errstr\n"; my $sql = "SELECT ID, Name FROM ScriptDetails WHERE Name='$filenam +e'"; my $sth = $dbh->prepare ( $sql ); $sth->execute(); my @row = $sth->fetchrow_array(); if (exists $row[1] and $row[1] eq $filename) { #If run before \ exists update fields { my $sql = "UPDATE ScriptDetails SET LastModified=from_unix +time($mtime),LastRunTime='$runtime',LastRunDate=from_unixtime($rundat +e),LastRunBy='$currentuser', AvgRunTime = ((AvgRunTime + $runtime) / +2), TotalRuns = TotalRuns+1 WHERE ID='$row[0]' L +IMIT 1"; my $sth = $dbh->prepare ( $sql ); $sth->execute(); } } else { #If first time run, create entry { my $sql = "INSERT INTO ScriptDetails (Name, LastModified, +LastRunTime, LastRunDate, LastRunBy, AvgRunTime, TotalRuns) VALUES('$ +filename',from_unixtime($mtime),'$runtime',from_unixtime($rundate/100 +0),'$currentuser', '$runtime', '1')"; my $sth = $dbh->prepare ( $sql ); $sth->execute(); } } $sth->finish(); $dbh->disconnect(); } 1;

When I try and run it I get the following error.

Undefined subroutine &main::script_stats called at TLEQUERY.pl line 88.

Any hints? First time using packages. Least I got it to find it.

Replies are listed 'Best First'.
Re: Help using self-made but very simple Module
by almut (Canon) on Oct 12, 2009 at 14:42 UTC

    Add use Exporter; at the top of your module. I.e. (simplified):

    # your module ScriptUpdate.pm package ScriptUpdate; use Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(script_stats); sub script_stats { print "script_stats(): ...\n"; } 1; # the main program: #!/usr/bin/perl use lib "./Modules"; use ScriptUpdate; script_stats();

    Note that our @ISA = qw(Exporter); does not load Exporter.

    (Alternatively, add strictures... which will indirectly have the same effect, i.e. loading Exporter as a side effect under the hood... :)

      Got me farther, had 2 more error messages pop up, fixed them and now stuck on this one.

      Can't call method "mtime" without a package or object reference at Modules/ScriptUpdate.pm line 2

      This works if i use it as a sub_routine. I added the File::stat lib but still get the error.

      Here the code that line references.

      my $mtime = stat($filename)->mtime;

      This is in the package. Do I need to bless something? Reading up on bless now but that's all new to me.

        You'd need to use File::stat in the package, as by-name stat fields are not core Perl syntax.

        Alternatively, simply write (stat $filename)[9].

Re: Help using self-made but very simple Module
by toolic (Bishop) on Oct 12, 2009 at 14:33 UTC
    Did you forget to use ScriptUpdate; in your TLEQUERY.pl script?
      Nope, wouldn't get that error message if I left it out. I call as follows.

      use Modules::ScriptUpdate;

        use Modules::ScriptUpdate;

        If you load it like this, your package name should be Modules::ScriptUpdate accordingly, or else Exporter will alias main::script_stats() to Modules::ScriptUpdate::script_stats(), not ScriptUpdate::script_stats(), where it would reside in your case with a package name of ScriptUpdate...

        In more detail, the reason is that use Modules::ScriptUpdate; implcitly calls Modules::ScriptUpdate->import(), which in turn (via inheritance) calls Exporter->import() with the first parameter being "Modules::ScriptUpdate".  This then is the namespace used by Exporter, not what you specified in the module source with package. For this reason - when you use Exporter - package name and filename/path of the module have to match.

        use Modules::ScriptUpdate;

        The usual thing to do is to have the module name match the package name - ie in ScriptUpdate.pm it would be usual to declare package Modules::ScriptUpdate; instead of package ScriptUpdate; (as you have done).

        Cheers,
        Rob
        Yes, you would get that message if you forgot use:
        use strict; use warnings; script_stats(); __END__ Undefined subroutine &main::script_stats called at TLEQUERY.pl at line + 3.