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

Hi all,

I've been using Perl for the last 14 months (where I was a heavy Awk user prior to that) and now want to graduate to making my own packages. Defining the package seems fairly straight-forward using the template from perlmod, but I'm having difficulty trying to globalize my filehandle as I would rather not pass the filehandle explicitly into each of my subroutines, as each one will write into the file (there are ~15 small subroutines.)

Main code:

#!/usr/bin/env perl use strict; use warnings; #use diagnostics; use MyPkgDirectory::MyPkg; my $wmode = '>'; my $rmode = '<'; my $filename = "zz_file.txt"; #my $FH_text_W; # this doesn't work, lexical? our $FH_text_W; # can I globalize my filehandle? open($FH_text_W, $wmode, $filename) || die "ERROR: cannot open $filena +me for writing $!"; print "Debug: Filehandle is: $FH_text_W\n"; &samplewrite(10, "foofoo"); # I don't want to pass in the FH! close ($FH_text_W);

My package:

package MyPkgDirectory::MyPkg; # assumes MyPkgDirectory/MyPkg.pm use strict; use warnings; BEGIN { require Exporter; our $VERSION = 1.00; our @ISA = qw(Exporter); our @EXPORT = qw(samplewrite); } my $FH_text_W = $main::FH_text_W; #my $FH_text_W; sub samplewrite { my ($ver, $sheet) = @_; print "Debug: Version $ver\n"; print "Debug: SHEET $sheet\n"; print $FH_text_W "Version $ver\n"; # Bombs out here print $FH_text_W "SHEET $sheet\n"; # and here too } END { } 1;

The output when I run my testcase and the ensuing error message I'm getting is as follows:

Debug: Filehandle is: GLOB(0x3f8dac)

Debug: Version 10

Debug: SHEET foofoo

Can't use an undefined value as a symbol reference at MyPkgDirectory/MyPkg.pm line 21.

Thanks in advance,

Joe

Replies are listed 'Best First'.
Re: Globalize Filehandles and Visibility in Packages?
by NetWallah (Canon) on Mar 04, 2015 at 05:11 UTC
    You are getting bitten by the fact that the "use" statement is invoked as if it was inside a BEGIN block, so that the assignment:
    my $FH_text_W = $main::FH_text_W;
    Occurs before $main::FH_text_W is initialized.

    A more traditional perl/OO way to do this would be to make the package "MyPkgDirectory::MyPkg" a true object/class, with a "new" method that initializes the object.

    package MyPkgDirectory::MyPkg; # assumes MyPkgDirectory/MyPkg.pm use strict; use warnings; ... sub new{ my ($classname,$fh) = @_; die "File handle not specified" unless $fh; return bless {HANDLE => $fh}, $classname; } sub samplewrite { my ($self,$ver, $sheet) = @_; .... print {$self->{HANDLE}} "SHEET $sheet\n"; # Need funny braces to un +-confuse "print" }
    Then , in "main:
    ... # No Pre-declaration. the handle is now a local open(my $FH_text_W, $wmode, $filename) or die "ERROR: cannot open $f +ilename for writing $!"; my $pkg = MyPkgDirectory::MyPkg::->new( $FH_text_W); $pkg->samplewrite(10, "foofoo");

            "You're only given one little spark of madness. You mustn't lose it."         - Robin Williams

      Excellent. Thank you for taking the time to explain what I'm getting bit by. I really like the OO solution, but I'm afraid it is still a bit too far over my head. I want to get the whole package/module subject nailed down first. Then I will tackle OO.
Re: Globalize Filehandles and Visibility in Packages?
by vinoth.ree (Monsignor) on Mar 04, 2015 at 04:57 UTC
Re: Globalize Filehandles and Visibility in Packages? (dont)
by Anonymous Monk on Mar 04, 2015 at 10:11 UTC

    Use select

    In your module

    package Whatever; sub whatever { my $filehandle = select; print $filehandle ...; }

    In your program

    use Whatever; open my($fh)...; select $fh; whatever('whatever');

      Thanks anonymous. I didn't know about the select command. I know my method it isn't the preferred method or way to write good code, but the code is only for myself and no one else. Another suggestion I was given at work was to concatenate my strings together until I was complete. Then open the file and dump it all at once and immediately close the file. I just didn't want to drag around an ever-increasing string from one subroutine to another.

Re: Globalize Filehandles and Visibility in Packages?
by karlgoethebier (Abbot) on Mar 04, 2015 at 19:36 UTC

    Mmh, i wonder if Log::Message::Simple could do the job.

    Just an idea - but please take a look at GLOBAL-VARIABLES at the same place.

    Best regards, Karl

    «The Crux of the Biscuit is the Apostrophe»