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

hi everyone

linuxer made the following reply on a previous post of mine. I have a lot of questions about it so I decided to make a separate post.

"Even in a short test script you should check if open was successful. Especially when writing to a file."
my $output_file = 'hoser.txt'; # using three argument form and die if there's an error open my $fh, '>', $output_file or die "$output_file: open(w) failed: + $!"; my @file_info = stat $fh; or die "$output_file: stat failed: $! +"; close $fh or die "$output_file: close(w) failed
My question is ... why? Doesn't this take more work (ie for perl, longer runtime)? I suppose if you put an or, it'll simply skip over it if successful and cost nothing extra. Is this correct? Finally, is this good practice when developing code (error tracking) or do most include even in the final draft.

Replies are listed 'Best First'.
Re: file test operations
by Corion (Patriarch) on Feb 02, 2009 at 13:11 UTC

    Opening a file is slow anyway, and the additional error check doesn't cost you anything. And having Perl telling you the reason why it cannot create a file instead of the file silently not being created (or updated) is priceless. So, always check your open() calls for failure and output the error message together with the filename.

Re: file test operations
by jethro (Monsignor) on Feb 02, 2009 at 14:40 UTC

    Lets assume you have a program that takes one hour to run:

    somefunction() # takes 1 second to run foreach ( @bigmightarrayof360000 ) { someotherfunction($_); #takes 0,01 seconds to run }

    Now if you could throw away some error checking code in somefunction() to have its runtime down to 0,5 seconds, would you do it? Your program would gain an unnoticable speedup and in case of error either silently fail or even produce inconsistent data

    There are a few golden rules in optimization:

    * Don't optimize when you don't need to, i.e. if the program runs fast enough, don't optimize

    * Don't optimize prematurely

    * Don't optimize where it doesn't count. Usually say 5% of the code is responsible for 95% of the runtime. If you optimize in the other 95% of the code, you wasted your time for minimal gain

    * Optimization is a trade off. You might gain speed, but most of the time you lose on readability, memory usage, maintainability or safety. So be sure you can afford the loss.

    You might also like to read the section 'When to optimize' in Optimization_(computer_science)

Re: file test operations
by JavaFan (Canon) on Feb 02, 2009 at 13:26 UTC
    Doesn't this take more work (ie for perl, longer runtime)?
    Most certainly. But let me answer that with a counter question. If a simple check makes you concerned about longer runtimes, why do you use Perl?
Re: file test operations
by ikegami (Patriarch) on Feb 02, 2009 at 13:25 UTC
    stat doesn't require an open file handle. The following will do:
    my @file_info = stat($output_file) or die "$output_file: stat failed: $!\n";
Re: file test operations
by Bloodnok (Vicar) on Feb 02, 2009 at 13:21 UTC
    Corion, as usual, makes the case splendidly well. However, you could make your code a little more elegant, thro' the use of autodie or possibly the, now deprecated, Fatal module - both of which have the capability to devolve the error checking to perl itself - thus removing the explicit requirement for you to explicitly do the tests.

    A user level that continues to overstate my experience :-))
Re: file test operations
by apl (Monsignor) on Feb 02, 2009 at 15:22 UTC
    Assume you run your program (written efficiently without die statements), and hoser.txt does not get produced as you expected. What was the cause of the problem?
Re: file test operations
by linuxer (Curate) on Feb 02, 2009 at 16:58 UTC

    My code was well-formatted ;o) In case you want to use or copy code examples, please use the download link which should be shown below the code area. (I had to learn this lesson as well ;o))

    If your open fails, the corresponding filehandle doesn't work and all following commands, which use that filehandle will run into errors or/and will print warnings (if enabled; which generally should be done).

    By checking the success of the open, you can define what to do if it was successful, and what to do if not.

    If you want to read from a file:

    open my $fh, '<', $not_existent_filename; while ( my $line = <$fh> ) { print $line; } close $fh; print "END OF READ\n";

    If warnings are enabled, you'll get a warning about "readline() on closed filehandle", but you cannot distinguish between this failure and an empty file.

    If you recognize a delay by one single "or die ..." (or by the three I had in my previous example) in your script execution, I'm very impressed ;o)

Re: file test operations
by neutron (Sexton) on Feb 02, 2009 at 16:55 UTC
    @ikegami, I opted to use the open file handle to both open the file and/or create it if it doesn't exist. I seem to have irritated a few people when posting for help the first time and not including that line.

    @javafan, I'm a newb so I don't really know all the benefits of each software package. Having said that, I gravitated towards Perl because of it's inherent regular expressions capabilities. I'm still working on Learning Perl (Schwartz) but hope to eventually make my way to CGI. Are there more efficient programming languages that I should be aware of?

    @jethro, great advice!! Will keep in mind.

      Are there more efficient programming languages that I should be aware of?

      Javafans answer was a bit sarcastic because it doesn't really make sense to ask about efficiency around an open (which is maybe a thousand times slower than the following test you are worried about.

      There are faster languages about, for example C/C++ and assembly language. But that doesn't mean that YOU are faster in programming them. Or that it is as much fun programming in them. Tasks that are done in perl with a few lines need sometimes hundreds of lines in C. Pray that you have a fitting library at hand.

      For example, Hashes are used extensively in modern languages like perl, they are the bred-and-butter data structure and used for 80% of all data storage in a program. In C/C++ you can either:
      a) use a self-made data structure perfectly fitting the job, you only need 5 days instead of 1 to write the program and it might be noticably faster or not.
      b)use a hash library to get nearly the comfort of perl but also the same speed as perl for the handling of the data structure

      Don't get me wrong, if speed is all you care about, then use C/C++. If you need to write programs that have to make full use of every single memory bit and processor cycle of your machine, use C/C++. If you need to write low level hardware driver stuff, use C/C++. If you want to write programs faster, securer, testable, have better debugging, with more ease, have more libraries to choose from, want to use hashes and regex and other modern features extensively, want to program for the web or other high-level areas (i.e. far form the hardware), use perl.

      Note that you can combine perl and C-code (with limits) so it is often possible to write perl code and optimize the critical code parts with C code, if run time is critical