smith
smith

Reputation: 3262

perl using files handles on used module

I have a perl module module.pm and a script.pl file which calls the module.pm is it possible that module.pm knows about files declared inside script.pl for example :

I have a file defination under script.pl something like this

use module;
open FILE,'>','file.txt' or die 'can\'t open file';

inide module.pm i want to use FILE handle for example :

package module

print FILE $value;

is it possible to do something like this and, if yes, how ?

Upvotes: 1

Views: 835

Answers (3)

derobert
derobert

Reputation: 51157

As Flimzy answers, you should not do this. There are better ways to accomplish whatever it is you're trying to accomplish. I'll cover some in a second.

You can open a file in a different namespace than your package—or print to one:

package module;
print main::FILE "some text\n";

alternatively, in your program:

open(module::FILE, '>', '/tmp/file');

You could use caller to find the caller's package (instead of just assuming main). That way, you could always use the caller's FILE.

Better ways

Anonymous filehandles stored in variables

You really should be using globs stored in scalars nowadays. In other words, your open call should look like this:

open my $file, '>', '/tmp/file'

Then $file is an ordinary scalar, and you can pass it around like you would any other variable. So, maybe you'd have this code in your module:

package module;
sub foo {
    my $dest = shift;
    print $dest "hello, world\n";
}
1;

And then in your program, after that open, you'd call module::foo($file).

Anonymous filehandles and OO

If you have a bunch of routines in module that all take the same output filehandle, it can get tedious to pass it around all the time. Instead, create an object:

package module;
use Moose;

has output_fh => (
    is => 'rw',
    required => 1,
);

sub foo {
    my $self = shift;
    print $self->output_fh "hello, world\n";
}

Then, in your non-module code, you do something like this:

open my $fh, … ;
my $obj = module->new(output_fh => $fh);
$obj->foo();

the advantage of this approach grows as you start to carry around more state in $obj.

Anonymous filehandles and localized package variables

If you don't want to go the OO approach (which is generally cleaner than this approach) you can do this in your module:

package module;
our $OUTPUT_FH = undef; # or sensible default

sub foo {
    print $OUTPUT_FH "hello, world\n";
}

and then in your non-module code:

open my $fh, … ;
local $module::OUTPUT_FH = $fh;

module::foo();

The local-ization will make sure that when your current block exits, the previous value of $module::OUTPUT_FH is restored. This will make subroutine calls work (without trampling each other's settings) as long as each subroutine that changes it localizes it first.

If you must work with pre-5.6 perl:

Perl 5.6 (released 2000-03-22, almost 12 years ago) introduced filehandle autovivification that makes that open my $fh, … line work. In earlier versions, you need to make the glob yourself. The Symbol module provides an easy way:

use Symbol qw(gensym ungensym);
my $fh = gensym; # not sure if pre-5.6 had geniosym; if so, use that instead
open $fh, …
⋮
close $fh;
ungensym $fh;

If you want to go before perl 5, which became stable in 1995, then you're on your own.

Upvotes: 3

dgw
dgw

Reputation: 13646

If you use lexical filehandles instead of Barewords it is possible.

use module ;
open( my $filehandle , '>' , 'output.txt' ) or die 'Cannot open.' ;
module::some_fun( $filehandle ) ;

and in module.pm

package module ;
sub some_fun {
  my ( $filehandle ) = @_ ;
  print $filehandle "Hello world.\n" ;
}
1 ;

Hope that helps.

Upvotes: 5

Jonathan Hall
Jonathan Hall

Reputation: 79604

It may be possible to do this if you don't use strict, but it's really bad practice. The better option is to pass the file handle to your module.pm method/function(s).

use module;
open my $FILE,'>','file.txt' or die 'can\'t open file';

somesub($FILE);

Then:

package module;

sub somesub {
    my $FILE = shift;
    ... 
}

Upvotes: 3

Related Questions