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

using warn instead or print STDERR?

by leocharre (Priest)
on Feb 26, 2009 at 18:14 UTC ( [id://746613]=perlquestion: print w/replies, xml ) Need Help??

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

I often use print STDERR ... for debugging. (Yes, I know, I'm a unique snowflake that way.)

Would it be safe to ..
$DEBUG and warn "Well then, please note that..\n";
instead of
$DEBUG and print STDERR "Well then, please note that..\n";

Would this be ok? Or is gratuitous usage of warn going to potentially leave a trail of muck on the system- and somehow that matters? Maybe there's some other reason not to use warn for debugging reasons?

Replies are listed 'Best First'.
Re: using warn instead or print STDERR?
by kennethk (Abbot) on Feb 26, 2009 at 18:23 UTC
    warn is certainly not going to leave any more muck on the system than sprinkled print STDERR would, and have the nice additional benefit that warnings can be caught using signal handling if so desired (%SIG{__WARN__}). You might also consider swapping to carp, which can provide more much more useful information on where a syntax error occurred.
Re: using warn instead or print STDERR?
by toolic (Bishop) on Feb 26, 2009 at 18:24 UTC
    One difference, according to warn, occurs if you have a __WARN__ handler:
    No message is printed if there is a $SIG{__WARN__} handler installed.

    Update: another subtle difference is that you get line info if you leave off the newline in warn (not sure why):

    use strict; use warnings; print STDERR "print\n"; warn "warn with newline\n"; warn "warn without newline"; __END__ print warn with newline warn without newline at z line 11.
Re: using warn instead or print STDERR?
by repellent (Priest) on Feb 26, 2009 at 18:25 UTC
    I like to use warn instead of print STDERR if only to someday take advantage of $SIG{__WARN__}:
    require Carp; $SIG{__WARN__} = sub { Carp::cluck(@_) }; # for use with debugger $SIG{__WARN__} = sub { $DB::single = 1 };
      if only to someday take advantage of $SIG{__WARN__}:

      I'm curious about this now since more than one person has brought this up. By the above statement do you mean: 1) You wish to one day write code to take advantage of signal capturing, or 2) You are waiting on something to be implemented?

      TIA.
        More like 1. $SIG{__WARN__} allows me to decide what to do with my warnings at some later time, without needing to substitute every warn() call if I need things differently. See %SIG.
        # debugger, please slow down when you see keyword $SIG{__WARN__} = sub { $DB::single = $_[0] =~ /keyword/; warn(@_) }

      Bit verbose perhaps? :)

      What about:

      $SIG{__WARN__} = \&Carp::cluck;
Re: using warn instead or print STDERR?
by Bloodnok (Vicar) on Feb 26, 2009 at 18:43 UTC
    I tend to use warn (and its relatives from Carp) in production code - debugging by printing to STDERR since, as has been pointed out elsewhere on this thread, warnings are trappable - indeed, my test harnesses (using Test::More), attempt to to verify that the code is/isn't doing something unexpected by catching warnings using...
    my $WARN; local $SIG{__WARN__} = sub { $WARN = "@_" }; . . my $WARN = ''; some_op(); like($WARN, '/^$/', 'some_op() - no warnings');

    Update:

    Added example call - for clarity.

    A user level that continues to overstate my experience :-))
Re: using warn instead or print STDERR?
by bellaire (Hermit) on Feb 26, 2009 at 20:07 UTC
    Nothing wrong with it, in addition to being able to trap warnings as others mention, using warn has these advantages:
    • It's fewer keystrokes. Less chance of typing print STEDRR by accident.
    • By default tells you the line number where it is output. This gives you more info for debugging for free.
      And with a simple package such as
      package SIGS; # We're going to use Carp so we can get longmess use Carp; use if (scalar grep {m{Carp}} (keys %INC)), "Carp::Heavy"; # Now redefine Carp::format_arg so we can dump refs too! no warnings qw(once redefine); *Carp::format_arg = sub { package Carp; my $arg=shift; if (not defined $arg) { $arg='undef'; } elsif (ref $arg) { # we'll use Data::Dumper require Data::Dumper; #no warnings qw(once); local $Data::Dumper::Indent=0; local $Data::Dumper::Terse=0; #use warnings; $arg=Data::Dumper::Dumper($arg); $arg=~ s/^\$VAR\d+\s*=\s*//; $arg=~ s/;\s*$//; } else { $arg=~ s/'/\\'/g; #no warnings qw(once); $arg=str_len_trim($arg,$Carp::Heavy::MaxArgLen); #use warnings; $arg="'$arg'" unless $arg =~ /^-?[\d.]+\z/; } $arg=~ s/([[:cntrl:]]|[[:^ascii:]])/sprintf("\\x{%x}",ord($1)) +/eg; return $arg; } if (scalar grep {m{^Carp}} (keys %INC)); use warnings; use strict; use warnings; # Someplace to put messages our (@Messages); INIT { ### program INIT ... close(STDERR); open(STDERR,'>','nul') or die ""; $SIG{__WARN__}= sub { return unless (defined($main::DEBUG) and $main::DEBUG); # Carp's longmess includes the at ... line ... so remove it fr +om $_[-1] my @a=@_; $a[-1]=~ s/ at .+? line \d+.$//s; # Save message and traceback push(@Messages,@a,Carp::longmess()); # and warn --- output goes to nul warn @_; }; $SIG{__DIE__}= sub { # Carp's longmess includes the at ... line ... so remove it fr +om $_[-1] my @a=@_; $a[-1]=~ s/ at .+? line \d+.$//s; # Save message and traceback push(@Messages,@a,Carp::longmess()); # and die --- output goes to nul and dies die @_; }; } # INIT; END { ### program END ... close(STDERR); if ($?) { # email @Messages from here print "Emailing these messages:\n"; print @Messages; }; } # END; 0 == 0;
      you can make
      use strict; use warnings; sub A { ((1 x shift) !~ m{^(11+)\1+$}) or die "argument is not prime" +; A(@_); }; warn "\$DEBUG testing!"; A(1,2,3,4,5); exit;
      cough up
      Emailing these messages: argument is not prime at SIGS.pl line 16 main::A(4, 5) called at SIGS.pl line 17 main::A(3, 4, 5) called at SIGS.pl line 17 main::A(2, 3, 4, 5) called at SIGS.pl line 17 main::A(1, 2, 3, 4, 5) called at SIGS.pl line 20
      by using the -m option.
Re: using warn instead or print STDERR?
by ELISHEVA (Prior) on Feb 27, 2009 at 02:34 UTC

    I use warn, carp, etc for permanent assertions and unexpected/garbled runtime inputs and system conditions that need to be part of production code. I use print STDERR for temporary statements to peek into problem code. This makes it easy for me to do a search and replace (just search for STDERR) after I've diagnosed the problem.

    For more permanent diagnostic abilities, I design my code so that repeatable test suites can "peek" at and verify the code's state. I find that more reliable than debugging by observation...and less work over the long run. Also it keeps the code uncluttered of assertions that only matter when debugging.

    Best, beth

Re: using warn instead or print STDERR?
by TGI (Parson) on Feb 27, 2009 at 00:20 UTC

    Thanks for asking such an interesting question. I learned from the responses.

    This is barely not offtopic, or something. I'd like to make a suggestion and ask a question.

    IMO, these kind of debugging output lines are a perfect place to use the dreaded postfix if. I find:

    warn "Watch out, there a llamas!\n" if $DEBUG;
    to be clearer than:
    $DEBUG and warn "Watch out, there a llamas!\n";

    I guess its becuase the short circuit in the 'and' is not part of the meaning of the English word. The use or for things like open(...) or die "Ugh." doesn't bother me, because the sense is the same in English as in Perl.

    Is there a particular reason you like to use the $DEBUG and ... form?


    TGI says moo

      Well.. Here's what I've done out of this discussion thread.
      It's a little bit mischievious.. but.. it's ok for now..

      Let's imagine script.pl

      #!/usr/bin/perl use strict; use Getopt::Std::Strict 'dh'; INIT { $SIG{__WARN__} = $opt_d ? sub { warn(" # @_\n") } : sub { 1 }; $opt_h and print usage() and exit; } warn "Hi there. I am stuff, very interersting stuff."; sub usage { "-d flag to see interesting stuff\n" }

      So essentially, I can code debug into an existing class or script, that simply turns warnings off or on via something like an option flag or a class DEBUG variable. Very sexy.

      Back to your point.

      Yes, I have to hand it to you .. "$DEBUG and ..." is not as clear as "... if $DEBUG". To the normal human being. I think I've been using and or ? : so much that you just start to think like the interpreter a little bit so.. it becomes part of your language at the time. I feel no difference between "x and y" and "y if x". Odd.

      "Three strikes and you're out"
Re: using warn instead or print STDERR?
by juster (Friar) on Feb 27, 2009 at 02:11 UTC

    One minor nuisance where warn+newline does not work the same as print+newline is when using CGI::Carp. Here's an example on my bash shell:

    justin:~ $ perl -MCGI::Carp -e ' warn "Warning with newline\n"; carp "Carp with newline\n"; print STDERR "Print with newline\n"' [Thu Feb 26 17:53:00 2009] -e: Warning with newline [Thu Feb 26 17:53:00 2009] -e: Carp with newline [Thu Feb 26 17:53:00 2009] -e: at -e line 3 Print with newline justin:~ $

    When I was trying to print some debugging messages using warn+newline the timestamps got a little spammy.

    BTW, carp and croak will append the line number that called them even if you end the message with a newline, unlike warn and die.

Re: using warn instead or print STDERR?
by educated_foo (Vicar) on Feb 27, 2009 at 04:33 UTC
    Meh, they both work fine. That said, I like to have a numerical debug level -- categories are too complicated, and on-or-off is too coarse -- and to write debugging statements like this:
    dprint 1, "this is debugging"
    Then you can implement dprint as e.g.
    sub dprint { my $level = shift; return unless $DEBUG >= $level; my ($file, $line) = (caller)[1,2]; print STDERR "$file:$line: @_\n"; }
Re: using warn instead or print STDERR? (Smart::Comments)
by toolic (Bishop) on Feb 27, 2009 at 17:57 UTC
    Another alternative to consider is Smart::Comments. Keep in mind that this module is categorized thusly, according to the author in his Categorized Damian Modules node:
    Damian modules that are specifically debugging and coding aids and which Damian uses himself during code development
      Damian Conway rocks. Smart::Comments rocks.

      Two problems. Well.. not problems but peculiarities.

      1) You can't turn off Smart::Comments at runtime because it's a code filter. So you can't turn if off and on via the cli, or from another package :-(
      You use it, or you don't. Yes, you can turn it off at certain places- but my point is, it's hard coded.

      2) Makes your shiznit run a little tiny weensy bit slower.

      I still love Smart::Comments- I use it a ton in my test suites, then just disable them or whatever when it goes to production.

      It's just sometimes I need to call forth all that the (installed/production) code can tell me about what the hell is going on in there-(although most of the time I don't need to know the count of rice grains that carp had with his thai food). And Smart::Comments is not a good choice for that.

Re: using warn instead or print STDERR?
by Anonymous Monk on Feb 26, 2009 at 18:18 UTC
    Sure, why not

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (8)
As of 2024-04-18 06:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found