•Re: To die or not to die
by merlyn (Sage) on Oct 28, 2002 at 18:43 UTC
|
You don't really want death, but you do want to check the return value. Use logic like this:
my %config;
if (open FH, "user.config.file") { # we have a previous save
... get %config from FH ...
close FH;
} elsif ($! !~ /no such file/i) {
die "config file: $!";
}
... now use %config ...
This way, if the previous config is found, it's used. Otherwise, if it's not because it's absent, we die.
Simple logic.
-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply. | [reply] [d/l] |
Re: To die or not to die
by nothingmuch (Priest) on Oct 28, 2002 at 18:40 UTC
|
You shouldn't always die - you should always be prepared. The open you specified will empty any existing file, or create an empty one if one doesn't exist. The open will fail if you haven't enough permissions, or something like that. If, however, you do something like open FH,"user1.cfg" or make_new_conf("user1.cfg");
Then you'd deal with the inexistant file problem you think you needn't deal with. Then, should the file be inexistant - the open will also fail, making a new conf file instead (provided you have defined such a sub). If other errors occur, the same sub will also be called)
Always be prepared for errors - you don't need to fatalise them, you don't need to even report them - just don't count on system calls to always succeed, as they may not.
Update: dyslexia strikes again - it seemed clear when i reviewed it... =P sorry.
-nuffin zz zZ Z Z #!perl | [reply] [d/l] |
Re: To die or not to die
by broquaint (Abbot) on Oct 28, 2002 at 18:41 UTC
|
I really don't care if the file doesn't exist initially since I'm going to build it if it doesn't.
While you may wish to build the file, it may not be so. Anything from incorrect permissions to a lack of disk space could get in your way, and this is when a judicious use of die() comes in handy. So when things aren't working you'll find out pretty quickly.
HTH
_________ broquaint
| [reply] |
Re: To die or not to die
by BrowserUk (Patriarch) on Oct 28, 2002 at 21:35 UTC
|
You could always check if the file exists before trying to open it, and use that to decide whether to open it for input or output. That way, you know that if it exists but you can't open it for input, the error is serious enough to warrent a die (or warn depending on your error handling).
if ( -e $file ) {
open FH, $file or die "Failed: $! trying open existing $file\
+n";
# read it
open FH, '>', $file or die "Failed: $! trying to re-open $file\n";
+
}
else {
open FH, '>'.$file or die "Failed: $! trying to create new $file\
+n";
# do stuff
}
This way, if you get out of the if/else, you know you have a file open for output ready for (re)writing.
It also means that you get a meaningful error msg if the file is read-only.
Nah! Your thinking of Simon Templar, originally played by Roger Moore and later by Ian Ogilvy | [reply] [d/l] |
|
|
It probably won't matter here, but that's a bad idea in general since you open up yourself to a race condition: the file might be created after the -e test but before the open by another process. You need an atomic operation:
if (open FH, "<", $file) {
# read it and do stuff
open FH, ">", $file or die "Failed: $! trying to re-open $file\n";
}
else {
# do stuff
open FH, ">", $file or die "Failed: $! trying to create new $file
+\n";
}
Also, use the three-argument form of open as I've said elsewhere in this thread.
Makeshifts last the longest. | [reply] [d/l] |
Re: To die or not to die
by Mr. Muskrat (Canon) on Oct 28, 2002 at 18:45 UTC
|
open FH, ">user1.cfg" or die "Couldn't open file;"
It does not matter if the user1.cfg exists prior to running the code. If it does not exist, it will be created. If it does exist, it will be overwritten. If you are unable to open the file for writing, you should not proceed with writing to the file. You will get errors when you attempt to write to a file that hasn't been opened for writing.
| [reply] [d/l] |
|
|
You're right. After thinking about what you had said, I should have put:
open FH, "user1.cfg" not ">user1.cfg"
Well at least that is what I was trying for initially.
There is no emoticon for what I'm feeling now.
| [reply] |
|
|
| [reply] |
Re: To die or not to die
by SpaceAce (Beadle) on Oct 28, 2002 at 18:58 UTC
|
You might want to write a generic reporting sub. I have a standard package of useful routines I use again and again in my programs and one of them is a subroutine that prints to STDOUT allows you to exit or not exit as you see fit.
Ie, open(INPUT, "<input.txt") || NoGo(error=>"Could not open file input.txt for reading", exit=>1);
That way you can report errors to yourself or the user and terminate the program if necessary with a minimum of hassle. This is best if you are only worried about success or failure and not the exact cause.
SpaceAce
| [reply] |
|
|
open(INPUT, "input.txt") or
warn("Could not open file input.txt $!\n");
Also, note that on the open(), the file is "input.txt" and not ">input.txt" as this will open the file for writing, destroying anything that might already be in the file and would only die or warn if the file could not be created (low disk space, permissions, etc).
One last thing, what's the difference between or and || in die or warn statements? I know one is numeric and the other string, but as far as usage in this example, is there a difference or purely syntatic sugar?
Thanks
--
Ben
"Naked I came from my mother's womb, and naked I will depart." | [reply] [d/l] |
|
|
open F, "config.txt" or $! !~ /no such file/i or die "config.txt error
+: $!";
... process F ...;
close F;
Warnings will have to be turned off because you'll be doing I/O on a closed filehandle. My other code posted earlier doesn't have that issue.
-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply. | [reply] [d/l] |
Re: To die or not to die
by Popcorn Dave (Abbot) on Oct 28, 2002 at 21:18 UTC
|
| [reply] |
Re: To die or not to die
by Aristotle (Chancellor) on Oct 29, 2002 at 21:03 UTC
|
I'll assume you use an array to store the defaults. Then I'd say something like:
chomp(my @checked_names = do {
open my $fh, "<", $config_file ? (<$fh>) :
$! =~ /no such file/i ? () :
die "Can't open $config_file to read: $!";
});
# ... do stuff with @checked_names
open my $fh, ">", $config_file or die "Can't open $config_file to writ
+e: $!";
print $fh map "$_\n", @checked_names;
close $fh;
Note the use of a lexical to hold the filehandle in the do block. This means the file will be auto-closed when the $fh goes out of scope at the end of the block: otherwise, we'd have to follow the ternary with a close, forcing us to store the file content in a temporary array to be able to return it.
Although from the looks of this, since the file is reopened for writing later anyway, there may not be much incentive to die on the read attempt even if the error was due to something other than a nonexistant file. YMMV
Update: merlyn is right, of course.
Makeshifts last the longest. | [reply] [d/l] |
|
|
Note the use of a lexical to hold the filehandle in the do block.
So noted.
But I don't see "require 5.006;" at the top of your code,
because you just made it non-portable for 5.005 sites.
I hope you're aware of that. If not, you are now. And so is anyone else reading this thread.
-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply.
| [reply] |
Re: To die or not to die
by Molt (Chaplain) on Oct 29, 2002 at 10:58 UTC
|
Not quite sure what you mean by the 'I really don't care if the file doesn't exist initially since I'm going to build it if it doesn't'. When a file is opened with the > prefix you're opening it to write to it, and any file already there of that name will be blanked anyway. When this open fails it means you can't build the file there, maybe you don't have write permissions, or maybe the filesystem is completely full.
If you're planning on building a file and open ">file" fails then you do have problems since you can't actually write to the file and dying is probably a good plan.
| [reply] |