Handling errors when working with files

Handling errors when working with files

am 29.12.2007 11:21:38 von oscar gil

--0-1053396370-1198923698=:37535
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Hello everybody,
I wanted to learn a bit more about how to handle errors when I am working with files, so I wrote this simple script to start with it where you can see that first I show the normal perl errors variables, then I try to delete a file and finally I show the errors variables again.
The file I try to delete exists and it is at the same directory and after the script the file is deleted, so it works.
What surprised me is that at the end of the script the '$!' is 'No such file or directory' and '$^E' is 'The system cannot find the file specified' though the file was deleted correctly, :-?.

My idea was to treat the '$!' when I am working with files but with this results I don't see how.
Let me tell you I am using this version of perl with Windows and I tried it both, Win2k and WinXP:
This is perl, v5.8.7 built for MSWin32-x86-multi-thread
(with 14 registered patches, see perl -V for more detail)

Here it is the script and afterwards there is the STDOUT exit.

----------------------------------------------------
#!/usr/bin/perl -w
use strict;

print "\n\n\nBEFORE:\n-----\n";
print '$@'." is ->$@<-\n";
print '$!'." is ->$!<-\n";
print '$^E'." is ->$^E<-\n";
print '$?'." is ->$?<-\n\n\n";

# I tried with open and with system()
#open (RD , "del pepe.txt |") or die "I cannot RD\n";
system ("del pepe.txt");

print "AFTER:\n----\n";
print '$@'." is ->$@<-\n";
print '$!'." is ->$!<-\n";
print '$^E'." is ->$^E<-\n";
print '$?'." is ->$?<-\n\n\n";

#close RD;
-------------------------------------------------------

...and I got this as result:

-------------------------------------------------------
BEFORE:
-----
$@ is -><-
$! is -><-
$^E is -><-
$? is ->0<-



AFTER:
----
$@ is -><-
$! is ->No such file or directory<-
$^E is ->The system cannot find the file specified<-
$? is ->0<

------------------------------------------------------------

Questions:

1.- Why a have the '$!' and '$^E' set as it could not find the file when in reality it could?
I tried with 'system()' and with 'open' with the same results. :-(

Any help is welcome,
Thanks in advance.
Regards.



---------------------------------
Looking for last minute shopping deals? Find them fast with Yahoo! Search.
--0-1053396370-1198923698=:37535--

Re: Handling errors when working with files

am 29.12.2007 17:08:21 von krahnj

oscar gil wrote:
> Hello everybody,

Hello,

> I wanted to learn a bit more about how to handle errors when I am
> working with files,

Do you want to handle errors or do you want to report errors?

> so I wrote this simple script to start with it
> where you can see that first I show the normal perl errors variables,
> then I try to delete a file and finally I show the errors variables
> again.
> The file I try to delete exists and it is at the same directory and
> after the script the file is deleted, so it works.
> What surprised me is that at the end of the script the '$!' is 'No such=

> file or directory' and '$^E' is 'The system cannot find the file
> specified' though the file was deleted correctly, :-?.
> =20
> My idea was to treat the '$!' when I am working with files but with
> this results I don't see how.

Have you read the documentation for the variables you are using?

perldoc perlvar

$CHILD_ERROR
$? The status returned by the last pipe close, backtick (=91=
=91)
command, successful call to wait() or waitpid(), or from
the system() operator. This is just the 16-bit status
word returned by the wait() system call (or else is made
up to look like it). Thus, the exit value of the
subprocess is really ("$? >> 8"), and "$? & 127" gives
which signal, if any, the process died from, and "$? &
128" reports whether there was a core dump.
(Mnemonic: similar to sh and ksh.)

$OS_ERROR
$ERRNO
$! If used numerically, yields the current value of the C
"errno" variable, or in other words, if a system or
library call fails, it sets this variable. This means
that the value of $! is meaningful only immediately after=

a failure:

$EXTENDED_OS_ERROR
$^E Error information specific to the current operating
system. At the moment, this differs from $! under only
VMS, OS/2, and Win32 (and for MacPerl). On all other
platforms, $^E is always just the same as $!.
[ SNIP ]
Under Win32, $^E always returns the last error
information reported by the Win32 call "GetLastError()"
which describes the last error from within the Win32 API.=

Most Win32-specific code will report errors via $^E.
ANSI C and Unix-like calls set "errno" and so most
portable Perl code will report errors via $!.

Caveats mentioned in the description of $! generally
apply to $^E, also. (Mnemonic: Extra error explanation.)=


$EVAL_ERROR
$@ The Perl syntax error message from the last eval()
operator. If $@ is the null string, the last eval()
parsed and executed correctly (although the operations
you invoked may have failed in the normal fashion).
(Mnemonic: Where was the syntax error "at"?)

> Let me tell you I am using this version of perl with Windows and I
> tried it both, Win2k and WinXP:
> This is perl, v5.8.7 built for MSWin32-x86-multi-thread
> (with 14 registered patches, see perl -V for more detail)
> =20
> Here it is the script and afterwards there is the STDOUT exit.
> =20
> ----------------------------------------------------
> #!/usr/bin/perl -w
> use strict;
> =20
> print "\n\n\nBEFORE:\n-----\n";
> print '$@'." is ->$@<-\n";
> print '$!'." is ->$!<-\n";
> print '$^E'." is ->$^E<-\n";
> print '$?'." is ->$?<-\n\n\n";
> =20
> # I tried with open and with system()
> #open (RD , "del pepe.txt |") or die "I cannot RD\n";

Only the $! or $^E variables apply after open() *FAILS*. If open()=20
completed successfully then the values of $! and $^E are meaningless.


> system ("del pepe.txt");

Only the $? variable applies to the system() function. I think that=20
'del' is an internal command.com function (I haven't used DOS/Windows in =

a long time) so $? will probably report the return status of command.com?=



[ SNIP ]

> Questions:
>=20
> 1.- Why a have the '$!' and '$^E' set as it could not find the file
> when in reality it could?

Because the values of $! and $^E are only valid after an error occured.

> I tried with 'system()' and with 'open' with the same results. :-(


John
--=20
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall


--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Handling errors when working with files

am 29.12.2007 18:18:56 von oscar gil

--0-1458950237-1198948736=:27503
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Thanks John for your quick answer.

what you said about:

>Only the $? variable applies to the system() function. I think that
>'del' is an internal command.com function (I haven't used DOS/Windows
>in a long time) so $? will probably report the return status of
> command.com?

...seems to be true:

This is what is reported if the file 'pepe.txt' does not exist using 'system()':
"
BEFORE:
-----
$@ is -><-
$! is -><-
$^E is -><-
$? is ->0<-
Could Not Find G:\Oscar\Computing\Perl\Proyectos\PCshutdownScript\pepe.txt
(above a normal system error from 'del' command, I guess)
AFTER:
----
$@ is -><-
$! is ->No such file or directory<-
$^E is ->The system cannot find the file specified<-
$? is ->256<- (The value is not 0)
"
... and this is what is reported when the file 'pepe.txt' does not exist using 'open':

"
BEFORE:
-----
$@ is -><-
$! is -><-
$^E is -><-
$? is ->0<-

AFTER:
----
$@ is -><-
$! is ->No such file or directory<-
$^E is ->The system cannot find the file specified<-
$? is ->0<-

Could Not Find G:\Oscar\Computing\Perl\Proyectos\PCshutdownScript\pepe.txt
"

...but - What happens if I use 'open'? I cannot see any difference if the file 'pepe.txt' exists or not :-?

This is what is reported when the file 'pepe.txt' exists using 'open':

"
BEFORE:
-----
$@ is -><-
$! is -><-
$^E is -><-
$? is ->0<-

AFTER:
----
$@ is -><-
$! is ->No such file or directory<-
$^E is ->The system cannot find the file specified<-
$? is ->0<-
"
:-?
Using 'open' I cannot say if the 'del' command was done correctly or not, although there is a message probably to STDERR that I do not know how to manage. :-(

So far, I use 'open' a lot because if I open a file I can manage the information using the file handler.
Answering your question to 'Do you want to handle errors or do you want to report errors?'
I would like to handle the errors and I thought using these variable would be a good method, wouldn't be?
Thanks again.



"John W. Krahn" wrote:
oscar gil wrote:
> Hello everybody,

Hello,

> I wanted to learn a bit more about how to handle errors when I am
> working with files,

Do you want to handle errors or do you want to report errors?

> so I wrote this simple script to start with it
> where you can see that first I show the normal perl errors variables,
> then I try to delete a file and finally I show the errors variables
> again.
> The file I try to delete exists and it is at the same directory and
> after the script the file is deleted, so it works.
> What surprised me is that at the end of the script the '$!' is 'No such
> file or directory' and '$^E' is 'The system cannot find the file
> specified' though the file was deleted correctly, :-?.
>
> My idea was to treat the '$!' when I am working with files but with
> this results I don't see how.

Have you read the documentation for the variables you are using?

perldoc perlvar

$CHILD_ERROR
$? The status returned by the last pipe close, backtick (‘‘)
command, successful call to wait() or waitpid(), or from
the system() operator. This is just the 16-bit status
word returned by the wait() system call (or else is made
up to look like it). Thus, the exit value of the
subprocess is really ("$? >> 8"), and "$? & 127" gives
which signal, if any, the process died from, and "$? &
128" reports whether there was a core dump.
(Mnemonic: similar to sh and ksh.)

$OS_ERROR
$ERRNO
$! If used numerically, yields the current value of the C
"errno" variable, or in other words, if a system or
library call fails, it sets this variable. This means
that the value of $! is meaningful only immediately after
a failure:

$EXTENDED_OS_ERROR
$^E Error information specific to the current operating
system. At the moment, this differs from $! under only
VMS, OS/2, and Win32 (and for MacPerl). On all other
platforms, $^E is always just the same as $!.
[ SNIP ]
Under Win32, $^E always returns the last error
information reported by the Win32 call "GetLastError()"
which describes the last error from within the Win32 API.
Most Win32-specific code will report errors via $^E.
ANSI C and Unix-like calls set "errno" and so most
portable Perl code will report errors via $!.

Caveats mentioned in the description of $! generally
apply to $^E, also. (Mnemonic: Extra error explanation.)

$EVAL_ERROR
$@ The Perl syntax error message from the last eval()
operator. If $@ is the null string, the last eval()
parsed and executed correctly (although the operations
you invoked may have failed in the normal fashion).
(Mnemonic: Where was the syntax error "at"?)

> Let me tell you I am using this version of perl with Windows and I
> tried it both, Win2k and WinXP:
> This is perl, v5.8.7 built for MSWin32-x86-multi-thread
> (with 14 registered patches, see perl -V for more detail)
>
> Here it is the script and afterwards there is the STDOUT exit.
>
> ----------------------------------------------------
> #!/usr/bin/perl -w
> use strict;
>
> print "\n\n\nBEFORE:\n-----\n";
> print '$@'." is ->$@<-\n";
> print '$!'." is ->$!<-\n";
> print '$^E'." is ->$^E<-\n";
> print '$?'." is ->$?<-\n\n\n";
>
> # I tried with open and with system()
> #open (RD , "del pepe.txt |") or die "I cannot RD\n";

Only the $! or $^E variables apply after open() *FAILS*. If open()
completed successfully then the values of $! and $^E are meaningless.


> system ("del pepe.txt");

Only the $? variable applies to the system() function. I think that
'del' is an internal command.com function (I haven't used DOS/Windows in
a long time) so $? will probably report the return status of command.com?


[ SNIP ]

> Questions:
>
> 1.- Why a have the '$!' and '$^E' set as it could not find the file
> when in reality it could?

Because the values of $! and $^E are only valid after an error occured.

> I tried with 'system()' and with 'open' with the same results. :-(


John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall


--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/





---------------------------------
Looking for last minute shopping deals? Find them fast with Yahoo! Search.
--0-1458950237-1198948736=:27503--

Re: Handling errors when working with files

am 29.12.2007 18:43:37 von Tom Phoenix

On Dec 29, 2007 9:18 AM, oscar gil wrote:

> Using 'open' I cannot say if the 'del' command was done correctly
> or not, although there is a message probably to STDERR that I do
> not know how to manage. :-(

I believe you're talking about a piped open() to an external command.
The return value from the piped open indicates merely whether the open
itself was successful. The result of the command's execution isn't
available when open returns, because the command has just then been
started, and it may not be done running for some time. Once you're
done running the command, the return value from close() tells you
whether it exited successfully.

Having said that, is the command you're running doing nothing more
important than deleting files and directories? In most cases, you can
do that more quickly, easily, and safely directly from within Perl.
See the unlink and rmdir functions in perlfunc.

Hope this helps!

--Tom Phoenix
Stonehenge Perl Training

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Handling errors when working with files

am 30.12.2007 20:11:11 von Tom Phoenix

On Dec 30, 2007 10:17 AM, oscar gil wrote:

> What I still don't understand is why $! and $^E are set as there was an
> error though there was not :-?.

Those variables may be set when your perl binary internally needs to
use a system call or something similar. During or shortly after your
program uses open(), for example, perl has to make some several
complex system calls, some of which may fail without causing problems
at the Perl-programming level. The chief use of those variables is
just after certain operations have failed; after a success they may
have some irrelevant failure code left over from an unrelated
operation.

> Tom, How would you handle an error after an acction done on files,
> directories and so on?.

I'm not sure what you're asking for here. In most cases in Perl code,
the thing to do is to write something like "or die" with a good
diagnostic string wherever a key step might fail. It's common to need
to do some kind of cleanup after a failure; in Perl, that's often done
with an eval block, although an END block can also be useful,
depending upon the type of cleanup. But for some cases, it's easiest
to just use Perl's normal control structures:

foreach my $file (@lots_of_file_names) {
if (unlink $file) {
print "You'll never see '$file' again!\n";
} else {
print "Couldn't unlink '$file': $!; continuing...";
}
}

Hope this helps!

--Tom Phoenix
Stonehenge Perl Training

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/

Re: Handling errors when working with files

am 31.12.2007 11:13:05 von oscar gil

--0-1411355931-1199095985=:1427
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Thanks Tom, it helped. :-)

I learned some more few things. ;-)

Regards,

Tom Phoenix wrote:
On Dec 30, 2007 10:17 AM, oscar gil wrote:

> What I still don't understand is why $! and $^E are set as there was an
> error though there was not :-?.

Those variables may be set when your perl binary internally needs to
use a system call or something similar. During or shortly after your
program uses open(), for example, perl has to make some several
complex system calls, some of which may fail without causing problems
at the Perl-programming level. The chief use of those variables is
just after certain operations have failed; after a success they may
have some irrelevant failure code left over from an unrelated
operation.

> Tom, How would you handle an error after an acction done on files,
> directories and so on?.

I'm not sure what you're asking for here. In most cases in Perl code,
the thing to do is to write something like "or die" with a good
diagnostic string wherever a key step might fail. It's common to need
to do some kind of cleanup after a failure; in Perl, that's often done
with an eval block, although an END block can also be useful,
depending upon the type of cleanup. But for some cases, it's easiest
to just use Perl's normal control structures:

foreach my $file (@lots_of_file_names) {
if (unlink $file) {
print "You'll never see '$file' again!\n";
} else {
print "Couldn't unlink '$file': $!; continuing...";
}
}

Hope this helps!

--Tom Phoenix
Stonehenge Perl Training

--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/





---------------------------------
Never miss a thing. Make Yahoo your homepage.
--0-1411355931-1199095985=:1427--