SPUG: Looking for a graceful way to deal with file handles and modules

Doug Beaver dougb at scalar.org
Tue Sep 28 18:10:03 CDT 1999


On Tue, Sep 28, 1999 at 02:32:15PM -0700, caseyt at metaip.checkpoint.com wrote:
 
[ snip ]

> The solutions I can think of are:
> 
> 1. Open and close the file handle every time I write to it.
> 2. Have file handles open to the file in the module and the script at the
> same time.
> 
> Is there some graceful way that I can reference an open filehandle in my
> main script from the Perl module that has been called? Something pretty like
> main::filehandle? 

Filehandles are by definition globals, so you can't refer to it by
package name (I did a quick grep of the pods and didn't see anything
saying they weren't globals, so someone slap me if I'm wrong).  OTOH, I
think it's rather elegant/graceful/whatever to use Symbol::gensym() as
follows:

use strict;
use Symbol qw/gensym/;

my $fh = gensym;
open($fh, ">>$file") || die "Can't open $file: $!";

...

write_lines($fh, $msg);

sub write_lines {
    my ($fh, $msg) = @_;
    print $fh $msg;
}

__END__

You can find more documentation for Symbol by doing a `perldoc Symbol`.

I've loved Symbol ever since I wrote a logging module that mysteriously
wrote all log messages to a single log file once you were using more
than one object per program:

use DougbLog;

my $error_log = DougbLog->new($error_log_path);
my $blah_log  = DougbLob->new($blah_log_path);

...

$error_log->log("Invalid user input: %s", $input);
$blah_log->log("heh heh");

__END__

Both error messages went to $blah_log_path because my constructor did
this:

package DougbLog;

sub new {
    my $type = shift;
    my $class = ref($type) || $type;
    my $self = {};
    
    my $logfile = shift;
    unless (open(LOG, ">>$logfile")) {
        warn "Couldn't open $logfile: $!";
        return;
    }
    $self->{log_fh} = \*LOG;

    return bless $self => $class;
}
__END__

Since LOG is a global, each object's log_fh entry points to the last
file opened for appending with the LOG filehandle (oops!).  Generating a
filehandle inside the constructor with Symbol::gensym() fixed my
'problem', and made me a hero.  (Okay, I made the last part up...)

I realize that not everyone is going to make stupid mistakes like me,
but hopefully this will prevent someone from making the same one in the
future.  ;-)

HTH,

Doug

-- 
Smithers: I'm afraid we have a bad image, Sir.  Market research shows
          people see you as somewhat of an ogre.
   Burns: I ought to club them and eat their bones!

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    POST TO: spug-list at pm.org        PROBLEMS: owner-spug-list at pm.org
 Seattle Perl Users Group (SPUG) Home Page: http://www.halcyon.com/spug/
 SUBSCRIBE/UNSUBSCRIBE: Replace ACTION below by subscribe or unsubscribe
        Email to majordomo at pm.org: ACTION spug-list your_address





More information about the spug-list mailing list