Hiding Warnings that Relate to Intentional Code in Perl - perl

I have several warnings like the following that show up a lot when Perl is interpreting my code:
Smartmatch is experimental at /home/user/www/cgi-bin/safari/lib/SAFARI/Data.pm line 395.
And several from where I override a CPAN module's subroutine that contains bugs:
Subroutine Net::Amazon::S3::Client::Object::put_part redefined at /usr/local/share/perl5/FaithTree/Backup.pm line 65.
Both of these are intentional things in the code. I've found Smartmatch a wonderful tool that I'm intentionally using without any issues and I overrode those subroutines specifically because they didn't function properly in the upstream module. Is there a "proper" way to tell Perl not to show such warnings? If there's some need for them still, is there proper way to at least rein them in so it doesn't overwhelm server logs?
I read over on another question that I could use use experimental qw(smartmatch switch); to hide the Smartmatch warning. But I'm less certain what to do about the redefinition warning.

use experimental qw(feature ...);
to use experimental features without warnings. To suppress other warnings, run your code with a no warnings ... pragma enabled as described in the perldoc
no warnings 'redefine';
sub Someone::Elses::Package::my_monkey_patch_func { ... }
#c = (1, 2, undef, 4);
print join(";", #c); # emits warning
{
no warnings 'uninitialized';
print join(":", #c); # warning suppressed
}

Related

Can I `use strict` to observe runtime error? [duplicate]

When using use strict perl will generate a runtime error on unsafe constructs. Now I am wondering if it is possible to have it only print a warning instead of causing a runtime error ? Or is use warnings (or -w) warning about the same issues ?
No, use strict can't be made to issue warnings rather than die. All it does is set a few bits in the magic $^H variable, which triggers various things in the guts of the Perl interpreter.
No, use warnings isn't warning about the same things as use strict kills you for. For instance, use warnings will warn you about variables used only once (which might be the result of typos).
I'm gonna take a stab at guessing the real motivation here. Feel free to tell me if I guessed wrong.
I suspect your trying to tackle a large, older code base and would like to enable strictures but you were hoping first to get a sense of where the errors will be (and how many there are) without breaking functionality. Unfortunately, since use strict functions by modifying the internal behavior of the perl parser and interpreter, there isn't a 'loose strict' or, by analogy to html, any kind of 'transitional' mode.
However, you can tease apart the functionality of use strict to start moving in the right direction. First, note that there are actually three separate parts:
use strict 'refs'; # no symbolic references
use strict 'vars'; # must declare variables
use strict 'subs'; # no barewords
and of those only 'refs' generates runtime errors. So you could easily add use strict qw(vars subs) to each of your files (scripts and modules) and test them with perl -c. If you encounter any error messages, then comment out the use strict, or at least whichever of the two checks failed, and add a comment as to the nature of the failure and move on. This way you can quickly (depending on the number of files) determine which files have compile-time errors and come back to address them later. (If you were more motivated than me at the moment, you could even automate this process). Unless you have code that does scary things inside of BEGIN blocks, this should be pretty safe to do.
The trickier part is checking for the runtime errors generated by use strict 'refs' and unfortunately, there really isn't an easy way to do this because the errors are triggered by symbolic references which can't be determined by any kind of static analysis so -c and/or Perl::Critic are both useless.
Hopefully that gets closer to addressing your real problem.
The warnings and strict pragmas are complementary, not overlapping. The strict pragma has both compile-time and run-time effects. You can't reduce the severity of strictures from errors to warnings, but you can disable them entirely. For example, if you're writing your own export routine you'll need to enable symbolic references in order to manipulate the symbol table.
{
no strict 'refs';
# symrefs okay within this block
}
Warnings can also be disabled lexically (assuming you did use warnings instead of the largely obsolete -w flag).
Strictures and warnings provide a safety net. That's why they're recommended to be used by default. If you disable them you should disable only what's necessary and limit the change to the smallest possible scope.
The preferred method:
use Carp;
sub foo {
croak "no args" unless #_;
}
eval foo();
if( $# ){
print "caught die: $#";
}
If you can't change your die's to croak's:
sub foo {
die "no args" unless #_;
}
{
my $prev_die = $SIG{__DIE__};
$SIG{__DIE__} = sub { print "caught die: $_[0]"; };
eval foo();
$SIG{__DIE__} = $prev_die;
}
The second method will print out the errors on STDERR.
See:
perldoc -f eval
perldoc perlvar and search for /\$\#/ and /__DIE__/
perldoc Carp
Warnings can be made fatal — see perllexwarn — but strict errors can't be made non-fatal.
Why do you want to do that? I suspect an XY problem.

Why use strict and warnings?

It seems to me that many of the questions in the Perl tag could be solved if people would use:
use strict;
use warnings;
I think some people consider these to be akin to training wheels, or unnecessary complications, which is clearly not true, since even very skilled Perl programmers use them.
It seems as though most people who are proficient in Perl always use these two pragmas, whereas those who would benefit most from using them seldom do. So, I thought it would be a good idea to have a question to link to when encouraging people to use strict and warnings.
So, why should a Perl developer use strict and warnings?
For starters, use strict; (and to a lesser extent, use warnings;) helps find typos in variable names. Even experienced programmers make such errors. A common case is forgetting to rename an instance of a variable when cleaning up or refactoring code.
Using use strict; use warnings; catches many errors sooner than they would be caught otherwise, which makes it easier to find the root causes of the errors. The root cause might be the need for an error or validation check, and that can happen regardless or programmer skill.
What's good about Perl warnings is that they are rarely spurious, so there's next to no cost to using them.
Related reading: Why use my?
Apparently use strict should (must) be used when you want to force Perl to code properly which could be forcing declarations, being explicit on strings and subs, i.e., barewords or using refs with caution. Note: if there are errors, use strict will abort the execution if used.
While use warnings; will help you find typing mistakes in program like you missed a semicolon, you used 'elseif' and not 'elsif', you are using deprecated syntax or function, whatever like that. Note: use warnings will only provide warnings and continue execution, i.e., it won't abort the execution...
Anyway, it would be better if we go into details, which I am specifying below
From perl.com (my favourite):
use strict 'vars';
which means that you must always declare variables before you use them.
If you don't declare you will probably get an error message for the undeclared variable:
Global symbol "$variablename" requires explicit package name at scriptname.pl line 3
This warning means Perl is not exactly clear about what the scope of the variable is. So you need to be explicit about your variables, which means either declaring them with my, so they are restricted to the current block, or referring to them with their fully qualified name (for ex: $MAIN::variablename).
So, a compile-time error is triggered if you attempt to access a variable that hasn't met at least one of the following criteria:
Predefined by Perl itself, such as #ARGV, %ENV, and all the global punctuation variables such as $. Or $_.
Declared with our (for a global) or my (for a lexical).
Imported from another package. (The use vars pragma fakes up an import, but use our instead.)
Fully qualified using its package name and the double-colon package separator.
use strict 'subs';
Consider two programs
# prog 1
$a = test_value;
print "First program: ", $a, "\n";
sub test_value { return "test passed"; }
Output: First program's result: test_value
# prog 2
sub test_value { return "test passed"; }
$a = test_value;
print "Second program: ", $a, "\n";
Output: Second program's result: test passed
In both cases we have a test_value() sub and we want to put its result into $a. And yet, when we run the two programs, we get two different results:
In the first program, at the point we get to $a = test_value;, Perl doesn't know of any test_value() sub, and test_value is interpreted as string 'test_value'. In the second program, the definition of test_value() comes before the $a = test_value; line. Perl thinks test_value as sub call.
The technical term for isolated words like test_value that might be subs and might be strings depending on context, by the way, is bareword. Perl's handling of barewords can be confusing, and it can cause bug in program.
The bug is what we encountered in our first program, Remember that Perl won't look forward to find test_value(), so since it hasn't already seen test_value(), it assumes that you want a string. So if you use strict subs;, it will cause this program to die with an error:
Bareword "test_value" not allowed while "strict subs" in use at
./a6-strictsubs.pl line 3.
Solution to this error would be
Use parentheses to make it clear you're calling a sub. If Perl sees $a = test_value();,
Declare your sub before you first use it
use strict;
sub test_value; # Declares that there's a test_value() coming later ...
my $a = test_value; # ...so Perl will know this line is okay.
.......
sub test_value { return "test_passed"; }
And If you mean to use it as a string, quote it.
So, This stricture makes Perl treat all barewords as syntax errors. A bareword is any bare name or identifier that has no other interpretation forced by context. (Context is often forced by a nearby keyword or token, or by predeclaration of the word in question.) So If you mean to use it as a string, quote it and If you mean to use it as a function call, predeclare it or use parentheses.
Barewords are dangerous because of this unpredictable behavior. use strict; (or use strict 'subs';) makes them predictable, because barewords that might cause strange behavior in the future will make your program die before they can wreak havoc
There's one place where it's OK to use barewords even when you've turned on strict subs: when you are assigning hash keys.
$hash{sample} = 6; # Same as $hash{'sample'} = 6
%other_hash = ( pie => 'apple' );
Barewords in hash keys are always interpreted as strings, so there is no ambiguity.
use strict 'refs';
This generates a run-time error if you use symbolic references, intentionally or otherwise.
A value that is not a hard reference is then treated as a symbolic reference. That is, the reference is interpreted as a string representing the name of a global variable.
use strict 'refs';
$ref = \$foo; # Store "real" (hard) reference.
print $$ref; # Dereferencing is ok.
$ref = "foo"; # Store name of global (package) variable.
print $$ref; # WRONG, run-time error under strict refs.
use warnings;
This lexically scoped pragma permits flexible control over Perl's built-in warnings, both those emitted by the compiler as well as those from the run-time system.
From perldiag:
So the majority of warning messages from the classifications below, i.e., W, D, and S can be controlled using the warnings pragma.
(W) A warning (optional)
(D) A deprecation (enabled by default)
(S) A severe warning (enabled by default)
I have listed some of warnings messages those occurs often below by classifications. For detailed info on them and others messages, refer to perldiag.
(W) A warning (optional):
Missing argument in %s
Missing argument to -%c
(Did you mean &%s instead?)
(Did you mean "local" instead of "our"?)
(Did you mean $ or # instead of %?)
'%s' is not a code reference
length() used on %s
Misplaced _ in number
(D) A deprecation (enabled by default):
defined(#array) is deprecated
defined(%hash) is deprecated
Deprecated use of my() in false conditional
$# is no longer supported
(S) A severe warning (enabled by default)
elseif should be elsif
%s found where operator expected
(Missing operator before %s?)
(Missing semicolon on previous line?)
%s never introduced
Operator or semicolon missing before %s
Precedence problem: open %s should be open(%s)
Prototype mismatch: %s vs %s
Warning: Use of "%s" without parentheses is ambiguous
Can't open %s: %s
These two pragmas can automatically identify bugs in your code.
I always use this in my code:
use strict;
use warnings FATAL => 'all';
FATAL makes the code die on warnings, just like strict does.
For additional information, see: Get stricter with use warnings FATAL => 'all';
Also... The strictures, according to Seuss
There's a good thread on perlmonks about this question.
The basic reason obviously is that strict and warnings massively help you catch mistakes and aid debugging.
Source: Different blogs
Use will export functions and variable names to the main namespace by
calling modules import() function.
A pragma is a module which influences some aspect of the compile time
or run time behavior of Perl. Pragmas give hints to the compiler.
Use warnings - Perl complains about variables used only once and improper conversions of strings into numbers. Trying to write to
files that are not opened. It happens at compile time. It is used to
control warnings.
Use strict - declare variables scope. It is used to set some kind of
discipline in the script. If barewords are used in the code they are
interpreted. All the variables should be given scope, like my, our or
local.
The "use strict" directive tells Perl to do extra checking during the compilation of your code. Using this directive will save you time debugging your Perl code because it finds common coding bugs that you might overlook otherwise.
Strict and warnings make sure your variables are not global.
It is much neater to be able to have variables unique for individual methods rather than having to keep track of each and every variable name.
$_, or no variable for certain functions, can also be useful to write more compact code quicker.
However, if you do not use strict and warnings, $_ becomes global!
use strict;
use warnings;
Strict and warnings are the mode for the Perl program. It is allowing the user to enter the code more liberally and more than that, that Perl code will become to look formal and its coding standard will be effective.
warnings means same like -w in the Perl shebang line, so it will provide you the warnings generated by the Perl program. It will display in the terminal.

Why doesn't Perl warn for the redeclaration of a my() variable in the same scope?

use strict;
my $world ="52";
my $in = "42" ;
my $world="42";
my $out = "good" ."good";
chop($out);
print $out;
Do not worry about the code.The question is that I used my $world in two different lines but compiler didn't give any error but if we consider C language's syntax then we will get the error because of the redeclaration of variable. Why don't perl gives any error for redeclaration. I have one more question: What is the size of a scalar variable ?
1/ Variable redeclaration is not an error. Had you included "use warnings" then you would get a warning.
2/ By "size of scalar variable" do you mean the amount of data that it can store? If that's the case, Perl imposes no arbitrary limits.
You seem to be posting a lot of rather simple questions very quickly. Have you considered reading "Learning Perl"?
The question is my $world i used it in two different lines but compiler said no error but to the c we get error as redclaration of variable but why not in perl.
Simply because Perl isn't C, and redefining a variable isn't an error condition.
It can be a cause of unexpected behaviour though and would be picked up if you had use warnings; (as has been suggested to you before).
What is the size of scalar variable ? is there any size?
Define 'size'. Bytes? Characters? Something else? You might be looking for length
Because Perl likes to be robust. If you had warnings turned on, you would have heard about it.
"my" variable $world masks earlier declaration in same scope at - line 7.
Although USUW (use strict; use warnings;) is a good development practice, so would be using autodie--if autodie worried about syntax warnings. But the following, concept is roughly the same, to make sure that you're not avoiding any warnings.
BEGIN { $SIG{__WARN__} = sub { die #_; }; }
The above code creates a signal handler for warnings that just dies instead. However, I think this is better for a beginner:
BEGIN {
$SIG{__WARN__}
= sub {
eval {
# take me out of the chain, to avoid recursion
delete $SIG{__WARN__};
# diag will install the warn handler we want to use.
eval 'use diagnostics;';
$SIG{__WARN__}->( #_ ); # invoke that handler
};
exit 1; # exit regardless of errors that might have cropped up.
};
}
Anywhere you want, you can tell perl that you are not interested in changing your code to issue a particular category of warnings (and diagnostics will tell you the category!) and if you explicitly tell perl no warnings 'misc', not only will it not warn you, but it will also not fire off the warning handler, which kills the program.
This will give you a more c-like feel--except that c has warnings too (so you could implement a lexical counter as well...oh well.)

Can 'use strict' warn instead of error

When using use strict perl will generate a runtime error on unsafe constructs. Now I am wondering if it is possible to have it only print a warning instead of causing a runtime error ? Or is use warnings (or -w) warning about the same issues ?
No, use strict can't be made to issue warnings rather than die. All it does is set a few bits in the magic $^H variable, which triggers various things in the guts of the Perl interpreter.
No, use warnings isn't warning about the same things as use strict kills you for. For instance, use warnings will warn you about variables used only once (which might be the result of typos).
I'm gonna take a stab at guessing the real motivation here. Feel free to tell me if I guessed wrong.
I suspect your trying to tackle a large, older code base and would like to enable strictures but you were hoping first to get a sense of where the errors will be (and how many there are) without breaking functionality. Unfortunately, since use strict functions by modifying the internal behavior of the perl parser and interpreter, there isn't a 'loose strict' or, by analogy to html, any kind of 'transitional' mode.
However, you can tease apart the functionality of use strict to start moving in the right direction. First, note that there are actually three separate parts:
use strict 'refs'; # no symbolic references
use strict 'vars'; # must declare variables
use strict 'subs'; # no barewords
and of those only 'refs' generates runtime errors. So you could easily add use strict qw(vars subs) to each of your files (scripts and modules) and test them with perl -c. If you encounter any error messages, then comment out the use strict, or at least whichever of the two checks failed, and add a comment as to the nature of the failure and move on. This way you can quickly (depending on the number of files) determine which files have compile-time errors and come back to address them later. (If you were more motivated than me at the moment, you could even automate this process). Unless you have code that does scary things inside of BEGIN blocks, this should be pretty safe to do.
The trickier part is checking for the runtime errors generated by use strict 'refs' and unfortunately, there really isn't an easy way to do this because the errors are triggered by symbolic references which can't be determined by any kind of static analysis so -c and/or Perl::Critic are both useless.
Hopefully that gets closer to addressing your real problem.
The warnings and strict pragmas are complementary, not overlapping. The strict pragma has both compile-time and run-time effects. You can't reduce the severity of strictures from errors to warnings, but you can disable them entirely. For example, if you're writing your own export routine you'll need to enable symbolic references in order to manipulate the symbol table.
{
no strict 'refs';
# symrefs okay within this block
}
Warnings can also be disabled lexically (assuming you did use warnings instead of the largely obsolete -w flag).
Strictures and warnings provide a safety net. That's why they're recommended to be used by default. If you disable them you should disable only what's necessary and limit the change to the smallest possible scope.
The preferred method:
use Carp;
sub foo {
croak "no args" unless #_;
}
eval foo();
if( $# ){
print "caught die: $#";
}
If you can't change your die's to croak's:
sub foo {
die "no args" unless #_;
}
{
my $prev_die = $SIG{__DIE__};
$SIG{__DIE__} = sub { print "caught die: $_[0]"; };
eval foo();
$SIG{__DIE__} = $prev_die;
}
The second method will print out the errors on STDERR.
See:
perldoc -f eval
perldoc perlvar and search for /\$\#/ and /__DIE__/
perldoc Carp
Warnings can be made fatal — see perllexwarn — but strict errors can't be made non-fatal.
Why do you want to do that? I suspect an XY problem.

warnings::warn and FATAL categories in Perl

I must be understanding the warnings documentation wrong. The way I read it, this code:
use warnings;
use warnings FATAL => 'all';
warnings::warn('numeric', 'blarg');
print "finished\n";
Should print the 'blarg' warning and die since I've asked for all warnings to be fatal. However, when I run the code I get:
$> /opt/local/bin/perl x.pl
blarg at x.pl line 3
finished
Can somone help me understand why I can't get warn to die?
Okay. This is ugly. I had a post half-prepared explaining this as a bug in warnings, and then I realized it's not, it's just a really evil subtlety in the way warnings works.
Warnings starts looking for a relevant stack frame to get the warning bits from in warnings::warn's caller's caller. The idea is that you're writing some module and you use warnings::warn or warnings::warnif in your functions, and whether or not the warning is printed (or fatal) depends on the use warnings setting in scope in the code that uses your module. There's no option provided to have it start at caller(1) instead of caller(2), so the effect you want isn't possible.
An example of code that does work (and demonstrates how this interface was expected to be used by whoever wrote it):
package Foo;
require warnings;
sub bail {
warnings::warnif('numeric', "You fool! You divided by zero!");
}
package main;
use warnings FATAL => all;
Foo::bail();
print "Will never be reached\n";
And you can't defeat the way it works by just adding another level of subroutines, because it takes the flags from the first caller that's in a different package from the caller of warn/warnif/enable/etc.