Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

When do filehandles close?

by Sprad (Hermit)
on Jul 22, 2004 at 23:32 UTC ( [id://376754]=perlquestion: print w/replies, xml ) Need Help??

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

According to the Camel, filehandles will automatically close if they're re-open()ed. And I'd bet they also close when the program terminates. But do they ever close at any other time?

For instance, say I have this sub:

sub writefile { open (FILE, ">>myfile.txt"); print FILE "hello\n"; }
Will myfile.txt still be in use outside of writefile()?

---
A fair fight is a sign of poor planning.

Replies are listed 'Best First'.
Re: When do filehandles close?
by tachyon (Chancellor) on Jul 22, 2004 at 23:51 UTC

    A filehandle will bet closed when:

    1. It is formally closed with close
    2. When it goes out of scope which occurs:
      1. If it is localised to a block and you exit said block, provided no closure of course
      2. When the program exits everything goes out of scope.

    Examples, no or die $! for clarity not form.

    open F, $file; close F; # F is closed { open my $fh, $file; } # $fh is closed open F, $file; exit 0; # program is gone and F is closed # closure { my $fh; sub append { unless ( $fh ) { open $fh, $file } } } # closure means $fh is not destroyed, $fh remains open until program e +xit

    cheers

    tachyon

      Missed one little thing;-) as the OP already pointed out, reopen implicitly close a file handler.

      However in this case $. (current line number for the last filehandle accessed) is not reset. I would prefer explicit close all the time simply because of this.

      Update

      Just add a piece of code for demon (name this script a.pl):

      use strict; use warnings; open(SCRIPT, "<", "a.pl"); <SCRIPT>; <SCRIPT>; print $., "\n"; #close(SCRIPT); open(SCRIPT, "<", "a.pl"); <SCRIPT>; print $., "\n";

      Try to comment or uncomment that close. If it is commented, print out:

      2 3

      If it is not commented:

      2 1
Re: When do filehandles close?
by jZed (Prior) on Jul 22, 2004 at 23:41 UTC
    Try for yourself (with the commented line commented and then uncommented):
    #!perl -w use strict; $|=1; writefile(); print FILE "goodbye\n"; print `cat tmptmp`; sub writefile { # local *FILE; open (FILE, ">tmptmp") or die $!; print FILE "hello\n"; }
Re: When do filehandles close?
by beable (Friar) on Jul 22, 2004 at 23:57 UTC

    Just for completeness, one other time when filehandles close is when you call close() on them. Also, please take a look at open() in perlfunc, where it says this:

    Using the constructor from the "IO::Handle" package (or one of its subclasses, such as "IO::File" or "IO::Socket"), you can generate anonymous filehandles that have the scope of whatever variables hold references to them, and automatically close whenever and however you leave that scope:
      You don't even need IO::File:
      { open my $fh, $file or die "open: $!"; $line = <$fh>; } # $fh is closed here

        Interesting... You made a little typo, that should be a semicolon on the end of the open() line. But look at this, it seems to solve pg's problem. And interestingly, IO::File has the same behaviour that pg is complaining about. Is this behaviour of $. a bug or a feature?

        #!/usr/bin/perl my $file = "pg-write3"; { open my $fh, $file or die "open: $!"; $line = <$fh>; $line = <$fh>; print "two reads:\t$.\n"; } # $fh is closed here print "closed file:\t$.\n"; { open my $fh, $file or die "open: $!"; print "open again:\t$.\n"; $line = <$fh>; print "one read:\t$.\n"; } # $fh is closed here print "closed again:\t$.\n"; __END__ Output: two reads: 2 closed file: 2 open again: 0 one read: 1 closed again: 1
Re: When do filehandles close?
by nothingmuch (Priest) on Jul 23, 2004 at 13:02 UTC
    This is, IMHO, one of the things in Perl that really wreaks of old age.

    The issue here is when the FILE symbol in the symbol table is trashed. Since it is global, this happens only when the program exits (global destruction).

    Exceptions to this are dynamically and lexically scoped file handles. With the traditional construct (open FILE simply creates FILE at the global scope) this is pretty voodoo.

    { local *FILE; # declare every FILE symbol ($FILE, @FILE, as well as + the handle) local open FILE, "<", "foo"; } print "open" if fileno(FILE); # nope.

    What happens in that example is that all the symbols from file are recreated when local is called, and then the new versions exist in place of their predecessors, until they go out of scope. Then *FILE is rolled back, and the new values are destroyed. So in effect, the FILE filehandle is destroyed, and thus closed, and the nothing that was there before local is restored in it's place.

    The "new" way to open filehandles, which exists from 5.8, is to pass an uninitialized lexical variable to open. I like this much better because it doesn't work with global symbols at all, and you don't have to use gensym from Symbol to generate "anonymous" filehandles.

    { open my $fh, "<", "foo"; print $fh "blah"; } # $fh is gone here

    The IO::Handle family of modules implements further encapsulations - each file handle becomes an object.

    To summarize, the filehandle is closed when the variable disappears, and probably the best way to get fine grained control of when variables disappear is to use variables that are not bound to global symbols, which aren't as flexible, but lexical ones. See Dominus's Coping with Scoping for more info on this.

    -nuffin
    zz zZ Z Z #!perl

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://376754]
Approved by rlb3
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (2)
As of 2024-04-24 16:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found