Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
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
Replies are listed 'Best First'.
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 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");

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.

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 scrutinizing the Monastery: (9)
As of 2015-07-31 08:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (275 votes), past polls