Which safety net do you use in Perl? - perl

Which safety net do you use?
use warnings;
or
use strict;
I know that
A potential problem caught by use
strict; will cause your code to stop
immediately when it is encountered,
while use warnings; will merely give a
warning (like the command-line switch
-w) and let your code run.
Still I want to know that which one is mostly used by the Perl-programmers. Which one they have seen being used the most?

Both, of course. If perl were designed today, use strict and use warnings would be the default behavior. It's just like having warnings turned on in a compiler - why would you not do that by default?

What you have doesn’t even start to be enough.
I use code approximating this as a starting point. It works well in my environment, although as always your mileage may vary.
#!/usr/bin/env perl
use v5.12;
use utf8;
use strict;
use autodie;
use warnings;
use warnings qw< FATAL utf8 >;
use feature qw< unicode_strings >;
use open qw< :std :utf8 >;
use charnames qw< :full >;
# These are core modules:
use Carp qw< carp croak confess cluck >;
use File::Basename qw< basename dirname >;
use Unicode::Normalize qw< NFD NFKD NFC NFKC >;
use Getopt::Long qw< GetOptions >;
use Pod::Usage qw< pod2usage >;
our $VERSION = v0.0.1;
$0 = basename($0); # shorter messages
## $| = 1;
$SIG{__DIE__} = sub {
confess "Uncaught exception: #_" unless $^S;
};
$SIG{__WARN__} = sub {
if ($^S) { cluck "Trapped warning: #_" }
else { confess "Deadly warning: #_" }
};
END {
local $SIG{PIPE} = sub { exit };
close STDOUT;
}
if (grep /\P{ASCII}/ => #ARGV) {
#ARGV = map { decode("UTF-8", $_) } #ARGV;
}
binmode(DATA, ":utf8");
## Getopt::Long::Configure qw[ bundling auto_version ];
if (!#ARGV && -t STDIN) {
print STDERR "$0: reading from stdin: type ^D to end, ^C to kill...\n";
}
while (<>) {
$_ = NFD($_);
# ...
print NFC($_);
}
exit;
=pod
=encoding utf8
=head1 NAME
=head1 SYNOPSIS
=head1 DESCRIPTION
=head1 OPTIONS
=head1 EXAMPLES
=head1 ERRORS
=head1 FILES
=head1 ENVIRONMENT
=head1 PROGRAMS
=head1 AUTHOR
=head1 COPYRIGHT AND LICENCE
=head1 REVISION HISTORY
=head1 BUGS
=head1 TODO
=head1 SEE ALSO
=cut
__END__
Your UTF-8 data goes here.
You can find more examples of this sort of thing in action in the Perl Unicode Tool Chest, currently up to around 50 files ranging from the simple to the sublime.

use strict generates an error if you use symbolic references (ie, strings to represent names of symbols). It generates an error if you use a variable without declaring it (this encourages the use of lexical 'my' variables, but is also satisfied if you properly declare package globals). It also generates an error if you leave barewords hanging around in the script (unquoted strings, essentially, by Perl's definition of quotes). With 'strict', you may enable or disable any of three categories of strictures, and my do so within scoped blocks. It is a best practice to enable strictures, though on occasion legitimate code requires that some of its features be locally disabled. However, one should think long and hard about whether this is really necessary, and whether their solution is ideal. You can read about strictures in Perl's POD entitled 'strict'.
use warnings generates a warning message based on many criteria, which are described in the POD 'perllexwarn'. These warnings have nothing to do with strictures, but rather, watch for the most common "gotchas" one is likely to encounter in their programming. It is a best practice to use warnings while writing scripts too. In some cases where the message might be undesirable a certain warning category may be locally disabled within a scope. Additional info is described in 'warnings'.
use diagnostics makes the warnings more verbose, and in a development or learning environment, particularly among newcomers, that's highly desirable. Diagnostics would probably be left out of a 'final product', but while in development they can be a really nice addition to the terse messages normally generated. You can read about diagnostics in the Perl POD "diagnostics."
There is no reason to force oneself to use only one of the above options or another. In particular, use warnings and use strict should generally both be used in modern Perl programs.
In all cases (except diagnostics, which you're only using for development anyway), individual strictures or warnings may be lexically disabled. Furthermore, their errors may be trapped with eval{ .... }, with Try::Tiny's try/catch blocks, and a few other ways. If there's a concern about a message giving a potential attacker more information about a script, the messages could be routed to a logfile. If there's a risk of said logfile consuming lots of space, there's a bigger issue at hand, and the source of the issue should either be resolved or in some rare cases simply have the message disabled.
Perl programs nowadays should be highly strict/warnings compliant as a best practice.

Use both, as the linked page says.
The documentation is perhaps a bit unclear. use strict and use warnings catch different problems; use strict will not cause your program to immediately exit when mere warnings are encountered, only when you violate the strict syntax requirements. You will still get only warnings printed when your code does things that are less seriously bad.

use strict;
#use warnings;
use diagnostics; # "This module extends the terse diagnostics..." by http://perldoc.perl.org/diagnostics.html
Both! But I prefer diagnostics, instead of warnings, which give you some more information.

Related

Wrapping Perl "die" and "warn" in a utility subroutine

I want to write a small subroutine that can decorate all error messages in a consistent way instead of having to copy it all around my program.
However I want the line numbers to be from where it was called, not from where the die/warn occurred.
In C I would just use a preprocessor macro, but Perl does not have those. What is the best way to implement this?
Use Carp for warnings/errors. You can use __WARN__ and __DIE__ hooks to affect what warn prints to the STDERR stream and how die is thrown. Note that they are quite different.
use warnings;
use strict;
use feature 'say';
use Carp;
$SIG{__WARN__} = \&wrap_warn;
sub wrap_warn {
print "WARNING: #_";
}
sub level_2 {
say "Print from level_2";
carp "carp from level_2(#_)";
}
sub level_1 {
level_2(#_);
}
level_1("from main");
prints to STDOUT
Print from level_2
WARNING: carp from level_2(from main) at wrap_warn.pl line 19.
main::level_2('from main') called at wrap_warn.pl line 15
main::level_1('from main') called at wrap_warn.pl line 22
If you want this to still go to STDERR then use print STDERR "WARNING: #_";
Make sure to carefully read about %SIG in perlvar and warn, at least.
While it seems that you want this to be global, I'd like to mention that one generally wants to local-ize changes like this one. There's an example in this post, and more out there.
Adding the following will add stack traces to exceptions and warnings:
use Carp::Always;
For the occasional use, use the following to avoid modifying your program:
perl -MCarp::Always script args
or
PERL5OPT=-MCarp::Always script args

Suppress uninitailized perl warning

Is there a way I can suppress uninitialized Perl variable warning for only few libraries out of all the libraries used in a Perl file?
I can't think of any reason this would be a good idea, surely use of an uninitialised variable is a bug which ever angle you look at it from?
However, you can turn the warnings off with:
no warnings 'uninitialized';
And on again with:
use warnings 'uninitialized';
You can disable the warnings for a single statement if you surround it with these two statements.
You probably used -w, which enables warnings throughout the interpreter (though it can be overridden using local $^W = 0; or no warnings;).
It's not a bad thing to use -w. All modules should tolerate this or defend against it (using no warnings;). But some aren't "warnings-safe".
It's more conventional to place use warnings; in each of your scripts and modules. This is method of enabling warnings is less intrusive since it won't affect other third-party modules used by your script and modules.
If you're able to modify the offending module(s), you can add no warnings 'uninitialized'; to the module itself, outside of any sub declarations, and it will disable that category of warnings for all code in the module, as demonstrated with these two bits of code:
In warntest:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
use lib '.';
use UndefMod;
my $x;
say "Main before: $x";
UndefMod::test_mod;
say "Main after: $x";
In UndefMod.pm (in the same directory):
package UndefMod;
use strict;
use warnings;
use 5.010;
no warnings 'uninitialized';
sub test_mod {
my $x;
say "Module: $x";
}
1;
When run, this produces "Use of uninitialized value" warnings for both says in warntest, but no warning for the say in UndefMod, thus showing that either file's warnings setting has no effect on the other.
Of course, you may not be able to modify the module source, in which case you may be out of luck. Perl's scoping rules don't generally allow you to modify the warnings/no warnings state of a scope from outside that scope. (I say "may" and "generally" because there may be some black magic to hack around that, probably at least related to the magic behind PadWalker, but such things are beyond my ken.)

How to get the set of warning checks currently enabled in the perl module?

In the perllexwarn are defined all warnings what is possible to set.
But here is nothing about, how to print out what warnings i have currently enabled.
E.g.:
use strict;
use warnings;
print warnings::enabled->pretty_print(); #fictional...
How is it possible?
example:
use strict;
use 5.012;
use warnings;
my $aaa;
say "$aaa";
say warnings::enabled("uninitialized") ? "yes" : "no";
The above will output:
Use of uninitialized value $aaa in string at y line 6.
no
so, the "uninitialized" warning category is "set", because its prints a warning, but the warnings::enabled("uninitialized") not returns true.
Reading perllexwarn
... functions that are useful for module authors. These are used when you
want to report a module-specific warning to a calling module has
enabled warnings via the "warnings" pragma.
If I understand it correctly, it means the functions (enabled, warnif) only work for module-specific warnings, not for the standard categories. (There is probably a missing "that" before "has" in the documentation.)
Update: It seems standard categories work as well, but only in a module:
package MY;
use warnings::register;
sub S {
my $x;
print $x, "\t";
print warnings::enabled("uninitialized"),"\n";
}
package main;
use warnings;
MY::S();
no warnings;
MY::S();

How to "use" multiple modules with one "use"?

I want use some packages and some pragmas in all my programs, like:
use 5.014;
use warnings;
use autodie;
use My::ModuleA::Something;
use ModuleB qw(Func1 Func2);
I don't want repeat myself in every module, so looking for a way how to make one package e.g. My::Common what will contain the above packages and in my programs do only:
use My::Common;
say Func1("hello"); #say enabled and Func1 imported in the My::Common
how to achieve this?
The was read preldoc -f use and perldoc perlmodlib so i think I must "somewhat" to do this with BEGIN plus require&import, but absolutely don't know how.
UPDATE: I'm already tried the basic things.
With require - my prg.pl program.
require 'mymods.pl';
$var = "hello";
croak "$var\n";
mymods.pl contain
use strict;
use feature 'say';
use Carp qw(carp croak cluck);
1;
DOES NOT WORKS. Got error:
$ perl prg.pl
String found where operator expected at prg.pl line 3, near "croak "$var\n""
(Do you need to predeclare croak?)
syntax error at prg.pl line 3, near "croak "$var\n""
Execution of prg.pl aborted due to compilation errors.
with "use My":
use My;
$var = "hello";
croak "$var\n";
my My.pm
package My;
use strict;
use feature 'say';
use Carp qw(carp croak cluck);
1;
DOES NOT WORKS either. Got the same error.
Any working idea?
I'd go with this:
package My::Common;
use 5.14.0;
use strict;
use warnings;
use autodie;
use Carp qw(carp croak cluck);
sub import {
my $caller = caller;
feature->import(':5.14');
# feature->import('say');
strict->import;
warnings->import;
## autodie->import; # <-- Won't affect the caller side - see my edit.
{
no strict 'refs';
for my $method (qw/carp croak cluck/) {
*{"$caller\::$method"} = __PACKAGE__->can($method);
}
}
}
1;
Please correct me if I'm wrong, or there's a better way.
EDIT:
Sorry, I was wrong in using autodie->import...
This one should work, but it assumes that you always call My::Common from the main package:
package My::Common;
# ...
sub import {
# ...
strict->import;
warnings->import;
{
package main;
autodie->import;
}
# ...
}
So, of course, it's much safer and simpler to add a use autodie; to each script:
use My::Common;
use autodie;
# ...
It's actually fairly simple, if you override your "common" module's import method. See the source of chromatic's Modern::Perl module for an example of exporting pragmas.
For re-exporting things defined in other modules, I seem to recall that $export_to_level (see the Exporter docs, although it's not explained all that clearly) should do that, although I can't find any good examples at the moment. Another option would be Pollute::persistent, although I haven't used it, don't know anyone else who's used it, and can't say how stable/solid it's likely to be. If it works, though, it's probably the quickest and easiest option.
I've just noticed a module called rig in CPAN. Try it out.

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.