in reply to Re: To Kill a Meme: while(defined($line = <>))
in thread To Kill a Meme: while(defined($line = <>))

A plea to not close a filehandle because Perl will close it for you?

Actually, this is one thing I always advise people to do - use lexical filehandles in tight scopes, and let their scoping take care of closing. That's much cleaner and easier to maintain than package filehandles.

It's related to the distinction between in control flow GOTO-driven and structured programs: you don't have to figure out the temporal sequence of code to understand where a filehandle comes into play and when its lifecycle ends, all you need is to look at the spatial layout of the source.

Makeshifts last the longest.

  • Comment on Don't close filehandles (was: To Kill a Meme: while(defined($line = <>)) )

Replies are listed 'Best First'.
Re: Don't close filehandles (was: To Kill a Meme: while(defined($line = <>)) )
by BrowserUk (Patriarch) on Nov 03, 2003 at 20:02 UTC

    Isn't it at least theoretically possible for close to return an error? I'm not sure what, if anything could be done to rectify it if it did, but it could be used to alter the course of the rest of the program, even if it was only to log an error and exit.

    Is there any way of trapping and handling such an error if you allow an unclosed lexical filehandle to just go out of scope?

    I guess if you where using IO::*, you could subclass the DESTROY method, but would the filehandle still be open at that point? Or would an error code be accessible?


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Hooray!
    Wanted!

      Isn't it at least theoretically possible for close to return an error?
      Yes, but that's normally only important for files open for writing, sockets and pipes. But usually you don't really care if you can't close a filehandle that you have open for reading.

      Abigail

        Granted. With respect to the OP's case of reading a file, but I took Aristotle to mean that he advises using locally scoped lexical file handles for the general case.

        I can't honestly claim that I usually check the return from close even on writable files. Little I'm doing is that critical at the moment, but I was wondering how you could handle the possibility of the error occuring with autoclosed filehandles?

        As I said, I'm not sure it would be possible to do much about it beyond logging the fact that a failure had occured, but that could be important for tracking down failures in critical applications. I just can't see a way to go about it when auto-closing lexical handles.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        Hooray!
        Wanted!

Re: Don't close filehandles (was: To Kill a Meme: while(defined($line = <>)) )
by ambrus (Abbot) on Nov 05, 2003 at 12:06 UTC
    I think this (letting perl close file automatically) is a bad idea. It does happen on NFS that close returns an error (when net connection breaks or quota is exceeded). (It can also happen if the disk is full or physically bad.) But Perl only gives a severe warning in this case, not an error, so if you don't see the warning (because cgi script or scrolled out of screen by make's messages), it will seem that it's run normally.
      Again, getting the return value of a close for a handle that's open for writing is useful. But for something that's open for reading?

      I am going to disagree with anyone who states that filehandles should be closed automatically, or who states that automatically closing is a bad idea because of the return value of close, if they don't distinguish the case of having something open for writing, and having something open for reading.

      Abigail

        You are right, I didn't think of that. It is OK to do it when the file is open for read-only.

      It's not something I thought of because nearly all of my scripts only read other files and write results to STDOUT.

      But it doesn't invalidate the approach, as even if I have to check the return value of close, I'll just put the check at the bottom of the scope. A pity that there's no more declarative way to do the check, but anyway.

      If anything, it can still be argued to be better than not using a scope in two ways: a) it reinforces a difference compared to read-only accesses (which won't have a close anywhere) and b) you cannot forget to close the filehandle even if you forget to check whether it was closed properly.

      Makeshifts last the longest.