Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

How to modify a warning message within a sub?

by Marshall (Prior)
on Aug 09, 2011 at 02:16 UTC ( #919360=perlquestion: print w/ replies, xml ) Need Help??
Marshall has asked for the wisdom of the Perl Monks concerning the following question:

Sometimes, one of my comparison subroutines causes a run-time warning. Perl has an amazing ability to do "something reasonable" in a situation like this and I am happy with what Perl does.

But the warning message doesn't tell me enough to go quickly to the input record that caused the problem. This is demonstrated below.

What I would like to do is: if a warning happens within compareLT105(), is to print something specific to this particular subroutine call, like: $arrayRef->[0] in addition to the Perl generated warning. That would narrow the field from ~1 million records to one record.

I don't want to "die", I just want to add something to the warning message. I read about installing a __WARN__ signal handler, but that appears to require exposing $arrayRef to a wider scope. Block eval{} works with "die".

This is of course a very simplistic version of the "real thing", but I hope provides enough info to get me on the right track.

I hope the solution is so easy that it is a "Duh!".

#!/usr/bin/perl -w use strict; $|=1; #turns off buffering for STDOUT my @x = ( [1,'100'], [2,'106'], [3,'100A'], [4,'100B2'], ); foreach my $ref (@x) { print "For $ref->[1] compareLT105 says: ", compareLT105($ref),"\n"; } sub compareLT105 { my $arrayRef = shift; return 'true' if $arrayRef->[1] < 105; return 'false'; } __END__ For 100 compareLT105 says: true For 106 compareLT105 says: false Argument "100A" isn't numeric in numeric lt (<) at C:\TEMP\warnexample +.pl line 21. For 100A compareLT105 says: true Argument "100B2" isn't numeric in numeric lt (<) at C:\TEMP\warnexampl +e.pl line 21. For 100B2 compareLT105 says: true

Comment on How to modify a warning message within a sub?
Select or Download Code
Re: How to modify a warning message within a sub?
by shmem (Canon) on Aug 09, 2011 at 02:45 UTC
    I read about installing a __WARN__ signal handler, but that appears to require exposing $arrayRef to a wider scope.

    No. Did you try? The trick is to install a local $SIG{__WARN__}:

    sub compareLT105 { my $arrayRef = shift; { # bare block to narrow scope of local() local $SIG{__WARN__} = sub { chomp( my $msg = $_[0] ); print STDERR $msg," \$arrayRef = [qw(@{$arrayRef})]\n"; }; return 'true' if $arrayRef->[1] < 105; } return 'false'; } For 100 compareLT105 says: true For 106 compareLT105 says: false Argument "100A" isn't numeric in numeric lt (<) at warn.pl line 27. $a +rrayRef = [qw(3 100A)] For 100A compareLT105 says: true Argument "100B2" isn't numeric in numeric lt (<) at warn.pl line 27. $ +arrayRef = [qw(4 100B2)] For 100B2 compareLT105 says: true
      THANKS!, I worked some more...this works..
      The good thing is that $arrayRef->[1] works without having $arrayRef having more scope than within the sub{}.

      #!/usr/bin/perl -w use strict; $|=1; #turns off buffering for STDOUT my @x = ( [1,'100'], [2,'106'], [3,'100A'], [4,'100B2'], ); foreach my $ref (@x) { print "For $ref->[1] compareLT105 says: ", compareLT105($ref),"\n"; } sub compareLT105 { my $arrayRef = shift; local $SIG{__WARN__} = sub { my $msg = shift; print STDERR $msg,"********"; print STDERR "error array index: ",$arrayRef->[0]; print STDERR " value is ",$arrayRef->[1], "\n"; }; return 'true' if $arrayRef->[1] < 105; return 'false'; } __END__ For 100 compareLT105 says: true For 106 compareLT105 says: false Argument "100A" isn't numeric in numeric lt (<) at C:\TEMP\warnexample +.pl line 30. ********error array index: 3 value is 100A For 100A compareLT105 says: true Argument "100B2" isn't numeric in numeric lt (<) at C:\TEMP\warnexampl +e.pl line 30. ********error array index: 4 value is 100B2 For 100B2 compareLT105 says: true
Re: How to modify a warning message within a sub?
by moritz (Cardinal) on Aug 09, 2011 at 05:01 UTC

    Another solution is to make warnings fatal (see perllexwarn) and then handle it all with eval. Disadvantage is that it will also catch ordinary errors.

    my $success = eval { use warnings FATAL => 'all'; risky_operation(); 1; }; unless ($success) { warn frob_message($!); }
      It's a good thought! But I think that the other solutions are a bit better.
Re: How to modify a warning message within a sub?
by Anonymous Monk on Aug 09, 2011 at 20:53 UTC
    If both files can be identically sorted, the Unix "merge" command can probably provide the answer with no further ado.
Re: How to modify a warning message within a sub?
by Monkomatic (Sexton) on Aug 09, 2011 at 22:33 UTC

    You could also just use the || command on whatever command you wanted to run and pipe the output out. and put a variable holder for the data line into the output.

    Like the following:

    open(DGRAB, $chunklookup) || die ("Could not open $chunklookup (DATA TO GRAB) \n");

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (16)
As of 2014-08-29 16:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (281 votes), past polls