I tried to catch a carp-warning:
carp "$start is > $end" if (warnings::enabled()); )
with eval {} but it didn't work, so I looked in the eval documentation and I discovered, that eval catches only syntax-errors, run-time-errors or executed die-statements.
How could I catch a carp warning?
#!/usr/bin/env perl
use warnings;
use strict;
use 5.012;
use List::Util qw(max min);
use Number::Range;
my #array;
my $max = 20;
print "Input (max $max): ";
my $in = <>;
$in =~ s/\s+//g;
$in =~ s/(?<=\d)-/../g;
eval {
my $range = new Number::Range( $in );
#array = sort { $a <=> $b } $range->range;
};
if ( $# =~ /\d+ is > \d+/ ) { die $# }; # catch the carp-warning doesn't work
die "Input greater than $max not allowed $!" if defined $max and max( #array ) > $max;
die "Input '0' or less not allowed $!" if min( #array ) < 1;
say "#array";
Based on your comments, my understanding is that you would like to make carp into a fatal warning.
If it is acceptable to make all carp warnings in your target package into fatal errors you can monkey-patch carp.
Carping Package:
package Foo;
use Carp;
sub annoying_sub {
carp "Whine whine whine";
}
Main program:
use Foo;
*Foo::carp = \&Foo::croak;
Foo::annoying_sub();
If you want to limit the monkey patch to a dynamic scope, you can use local:
use Foo;
Foo::annoying_sub(); # non-fatal
{ local *Foo::carp = \&Foo::croak;
Foo::annoying_sub(); # Fatal
}
carp does not die but just prints a warning, so there's nothing to catch with eval or whatever. You can, however, overwrite the warn handler locally to prevent the warning from being sent to stderr:
#!/usr/bin/env perl
use warnings;
use strict;
use Carp;
carp "Oh noes!";
{
local $SIG{__WARN__} = sub {
my ($warning) = #_;
# Replace some warnings:
if($warning =~ /replaceme/) {
print STDERR "My new warning.\n";
}
else {
print STDERR $warning;
}
# Or do nothing to silence the warning.
};
carp "Wh00t!";
carp "replaceme";
}
carp "Arrgh!";
Output:
Oh noes! at foo.pl line 8
Wh00t! at foo.pl line 25
My new warning.
Arrgh! at foo.pl line 29
In almost all cases you should prefer fixing the cause of the carp instead.
Related
Today I saw this piece of code:
if ( not defined($reply_address)
or not defined($from_name)
or not defined($subject)
or not defined($date) )
{
die "couldn’t glean the required information!";
}
(Jeffrey Friedl, "Mastering Regular Expressions", p. 59, 3rd ed.)
and I thought "How can I know which variable misfired?"
Of course, if there are only 4 variables to test, as in the example above, one could come up with:
if ( not defined $reply_address )
{
die "\$reply_address is not defined"
}
elsif ( not defined $from_name )
{
die "\$from_name is not defined"
}
elsif ...
But what if there are 14 variables? Or 40...?
One still needs to go through all of them, manually testing each and every one?
Isn't there a shorter, more "magical" way of telling which variable was left undefined?
You could create a table to simplify a little bit:
use strict;
use warnings;
my $reply_address = "xyz";
my $from_name;
my $subject = "test";
my $date;
my #checks = (
[\$reply_address, '$reply_adress'],
[\$from_name, '$from_name'],
[\$subject, '$subject'],
[\$date, '$date'],
);
for my $check (#checks) {
if (not defined ${$check->[0]}) {
die $check->[1] . " is not defined";
}
}
You can do what you want with symbolic references, though using them is generally not a great idea, and it can only be done with package variables, not lexically scoped variables (and lexically scoped variables are preferred to package variables -- see this answer for a brief comparison of the two).
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
our($foo1) = 1;
our($bar1) = undef;
our($baz1) = 3;
foreach my $name (qw(foo1 bar1 baz1)) {
{
no strict 'refs';
my($value) = $$name;
warn "$name: is not defined" unless defined $value;
say "$name: <$value>";
}
}
Using warn instead of die for illustrative purposes.
</tmp> $ ./test.pl
foo1: <1>
bar1: is not defined at ./test.pl line 16.
Use of uninitialized value $value in concatenation (.) or string at ./test.pl line 17.
bar1: <>
baz1: <3>
You can also just loop through all of the variables using common code to check them:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
my($foo2) = 1;
my($bar2) = undef;
my($baz2) = 3;
foreach my $vardef (["foo2", $foo2], ["bar2", $bar2], ["baz2", $baz2]) {
my($name) = $vardef->[0];
my($value) = $vardef->[1];
warn "$name: is not defined" unless defined $value;
say "$name: <$value>";
}
which gives similar output:
foo2: <1>
bar2: is not defined at ./test.pl line 29.
Use of uninitialized value $value in concatenation (.) or string at ./test.pl line 30.
bar2: <>
baz2: <3>
Finally, if you can manage to get the variables into a hash, you can loop through the keys of the hash and test them that way:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
my($vars) = {
foo3 => 1,
bar3 => undef,
baz3 => 3,
};
foreach my $name (sort keys %$vars) {
my($value) = $vars->{$name};
warn "$name: is not defined" unless defined $value;
say "$name: <$value>";
}
I threw the sort in there because I like deterministic behavior...
bar3: is not defined at ./test.pl line 42.
Use of uninitialized value $value in concatenation (.) or string at ./test.pl line 43.
bar3: <>
baz3: <3>
foo3: <1>
If the test really was as simple as die if ! defined then I would probably just list them out:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
my($foo4) = 1;
my($bar4) = undef;
my($baz4) = 3;
die qq([ERROR] \$foo4 not defined\n) unless defined $foo4;
die qq([ERROR] \$bar4 not defined\n) unless defined $bar4;
die qq([ERROR] \$baz4 not defined\n) unless defined $baz4;
which just gives us:
[ERROR] $bar4 not defined
The last approach is just very straightforward and unambiguous. If the test is not as dead simple as this, then I'd go with the second approach. If you're worried about a list of 40 (or even 14) checks of this nature, then I'd look at the design.
See also this PadWalker code example for a very complicated version of the first option, but allowing lexically scoped variables.
Could be done with a string-eval:
use strict;
use warnings;
my ($reply_address, $from_name, $subject, $date) = ('', '', undef, '');
for my $var (qw(reply_address from_name subject date)) {
my $defined;
eval "\$defined = defined \$$var";
die "eval failed: $#" if $#;
die "\$$var is not defined" unless $defined;
}
I am debugging a test in MPEG::Audio::Frame. If I run this test, I get:
$ cpan -g MPEG::Audio::Frame
$ tar zxvf MPEG-Audio-Frame-0.09.tar.gz
$ cd MPEG-Audio-Frame-0.09
$ perl Makefile.PL
$ make
$ perl -I./blib/lib t/04-tie.t
1..5
ok 1 - use MPEG::Audio::Frame;
ok 2 - 'tie' isa 'MPEG::Audio::Frame'
Not a HASH reference at blib/lib/MPEG/Audio/Frame.pm line 273, <DATA> line 1.
# Looks like your test exited with 255 just after 2.
I narrowed down the problem to the following minimal example:
package My::Module;
use feature qw(say);
use strict;
use warnings;
use overload '""' => \&asbin;
sub asbin {
my $self = shift;
$self->{binhead} # $self is not yet a hash, so execution stops here.
}
sub TIEHANDLE {
bless \$_[1], $_[0]
}
sub READLINE {}
sub read {
say "reading..";
my $pkg = shift;
my $fh = shift || 0; # Why is the stringification operator called here?
}
package main;
use feature qw(say);
use strict;
use warnings;
tie *FH, 'My::Module', *DATA;
My::Module->read(\*DATA);
<FH>;
__DATA__
abc
Why is the stringification operator called for the statement My::Module->read(\*DATA) ?
shift || 0 will want to coerce the argument in shift to a scalar. There is no boolify or numify function overloads defined for My::Module, so Perl will use your stringify function.
To avoid evaluating the object in scalar context, you could rephrase it as
my $fh = #_ ? shift : 0;
$fh = shift;
$fh = 0 unless ref($fh) || $fh;
or define a bool function overload.
I am trying to extract a DNA sequence from this FASTA file to a specified length of bases per line, say 40.
> sample dna (This is a typical fasta header.)
agatggcggcgctgaggggtcttgggggctctaggccggccacctactgg
tttgcagcggagacgacgcatggggcctgcgcaataggagtacgctgcct
gggaggcgtgactagaagcggaagtagttgtgggcgcctttgcaaccgcc
tgggacgccgccgagtggtctgtgcaggttcgcgggtcgctggcgggggt
Using this Perl module (fasta.pm):
package fasta;
use strict;
sub read_fasta ($filename) {
my $filename = #_;
open (my $FH_IN, "<", $filename) or die "Can't open file: $filename $!";
my #lines = <$FH_IN>;
chomp #lines;
return #lines;
}
sub read_seq (\#lines) {
my $linesRef = #_;
my #lines = #{$linesRef};
my #seq;
foreach my $line (#lines) {
if ($line!~ /^>/) {
print "$line\n";
push (#seq, $line);
}
}
return #seq;
}
sub print_seq_40 (\#seq) {
my $linesRef = #_;
my #lines = #{$linesRef};
my $seq;
foreach my $line (#lines) {
$seq = $seq.$line;
}
my $i= 0;
my $seq_line;
while (($i+1)*40 < length ($seq)) {
my $seq_line = substr ($seq, $i*40, 40);
print "$seq_line\n";
$i++;
}
$seq_line = substr ($seq, $i*40);
print "$seq_line\n";
}
1;
And the main script is
use strict;
use warnings;
use fasta;
print "What is your filename: ";
my $filename = <STDIN>;
chomp $filename;
my #lines = read_fasta ($filename);
my #seq = read_seq (\#lines);
print_seq_40 (\#seq);
exit;
This is the error I get
Undefined subroutine &main::read_fasta called at q2.pl line 13, <STDIN> line 1.
Can anyone please enlighten me on which part I did wrong?
It looks like you're getting nowhere with this.
I think your choice to use a module and subroutines is a little strange, given that you call each subroutine only once and the correspond to very little code indeed.
Both your program and your module need to start with use strict and use warnings, and you cannot use prototypes like that in Perl subroutines. Including a number of other bugs, this is a lot closer to the code that you need.
package Fasta;
use strict;
use warnings;
use 5.010;
use autodie;
use base 'Exporter';
our #EXPORT = qw/ read_fasta read_seq print_seq_40 /;
sub read_fasta {
my ($filename) = #_;
open my $fh_in, '<', $filename;
chomp(my #lines = <$fh_in>);
#lines;
}
sub read_seq {
my ($lines_ref) = $_[0];
grep { not /^>/ } #$lines_ref;
}
sub print_seq_40 {
my ($lines_ref) = #_;
print "$_\n" for unpack '(A40)*', join '', #$lines_ref;
}
1;
q2.pl
use strict;
use warnings;
use Fasta qw/ read_fasta read_seq print_seq_40 /;
print "What is your filename: ";
my $filename = <STDIN>;
chomp $filename;
my #lines = read_fasta($filename);
my #seq = read_seq(\#lines);
print_seq_40(\#seq);
You need to either:
add to your module:
use Exporter;
our #EXPORT = qw ( read_fasta
read_seq ); #etc.
call the code in the remote module explicitly:
fasta::read_fasta();
explicitly import the module sub:
use fasta qw ( read_fasta );
Also: General convention on modules is to uppercase the first letter of the module name.
In Perl, if you use fasta;, this does not automatically export all its methods into the namespace of your program. Call fasta::read_fasta instead.
Or: use Exporter to automatically export methods or enable something like use Fasta qw/read_fasta/.
For example:
package Fasta;
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT_OK = qw/read_fasta read_seq read_seq40/;
To use:
use Fasta qw/read_fasta read_seq read_seq40/;
You can also make Fasta export all methods automatically or define keywords to group methods, though the latter has caused me some problems in the past, and I would recommend it only if you are certain it is worth possible trouble.
If you want to make all methods available:
package Fasta;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw/read_fasta read_seq read_seq40/;
Note #EXPORT is not #EXPORT_OK. The latter allows importing them later (as I did), the former automatically exports all. The documentation I linked to makes this clear.
I just noticed something else. You are flattening #_ into $filename in read_fasta. I am not sure this works. Try this:
sub read_fasta {
my $filename = $_[0]; # or ($filename) = #_; #_ is an array. $filename not.
}
To explain the problem: $filename = #_; means: store #_ ( an ARRAY ) into $filename (a SCALAR). Perl does this in this way: ARRAY length is stored in $filename. That is not what you want. You want the first element of the array. That would be $_[0].
Added #ISA which is probably needed OR use comment by Borodir.
In the following code if there is space between FILE and ( in the printf statement
like
printf FILE ("Test string inline\n");
Perl will treat FILE as a filehandle otherwise
printf FILE("Test string inline\n");
will be treated as subroutine call(If no subroutine is defined by FILE perl will through an error Undefined subroutine &main::FILE called at ./test.pl line xx ). Isn't there a better way Perl can implement this ? (Maybe this is why bareword filehandles are considered outdated ?)
#!/usr/bin/perl
use warnings;
open(FILE,">test.txt");
printf FILE ("Test string inline\n");
close(FILE);
sub FILE
{
return("Test string subroutine\n");
}
Are you asking how to avoid that error accidentally? You could wrap the handle in curlies
printf({ HANDLE } $pattern, #args);
print({ HANDLE } #args);
say({ HANDLE } #args);
Or since parens are often omitted for say, print and printf,
printf { HANDLE } $pattern, #args;
print { HANDLE } #args;
say { HANDLE } #args;
Or you could use a method call
HANDLE->printf($pattern, #args);
HANDLE->print(#args);
HANDLE->say(#args);
Try:
#!/usr/bin/env perl
use strict;
use warnings;
# --------------------------------------
use charnames qw( :full :short );
use English qw( -no_match_vars ) ; # Avoids regex performance penalty
my $test_file = 'test.txt';
open my $test_fh, '>', $test_file or die "could not open $test_file: $OS_ERROR\n";
printf {$test_fh} "Test string inline" or die "could not print $test_file: $OS_ERROR\n";
close $test_fh or die "could not close $test_file: $OS_ERROR\n";
I am using reval from Perl's Safe module and I want to prevent it from generating warnings if the string being eval'ed can't be parsed (actually, I want to prevent it from generating any warnings at all).
For example, the following code:
use strict; use warnings;
use Safe;
use feature qw/say/;
my $cft = Safe->new;
my $x = $cft->reval(') 1' );
my $y = $cft->reval('2' );
say "x: $x";
say "y: $y";
results in:
Number found where operator expected at (eval 5) line 1, near ") 1"
(Missing operator before 1?)
Use of uninitialized value $x in concatenation (.) or string at ./test line 12.
x:
y: 2
What I'm trying to achieve is to have $x = undef and $y = 2, and no warnings.
I tried to put a "no warnings;" inside a new scope, but it has no effect on the warnings produced from within the reval (although, as pointed out by #DavidO, it silences the 'uninitialized value' warning):
use strict; use warnings;
use Safe;
use feature qw/say/;
my $cft = Safe->new;
{
no warnings;
my $x = $cft->reval(') 1' );
my $y = $cft->reval('2' );
say "x: $x";
say "y: $y";
}
I guess that somehow the 'no warnings' has to be inside the Safe compartment, so I also tried to prepend "no warnings;" to the strings being eval'ed:
use strict; use warnings;
use Safe;
use feature qw/say/;
my $cft = Safe->new;
{
my $x = $cft->reval( 'no warnings;' . ') 1' );
my $y = $cft->reval( 'no warnings;' . '2' );
say "x: $x";
say "y: $y";
}
This way reval does not issue any warnings, but both variables are undef:
Use of uninitialized value $x in concatenation (.) or string at ./test line 10.
x:
Use of uninitialized value $y in concatenation (.) or string at ./test line 11.
y:
I don't know what else to try, and I hope that the problem description was clear enough.
If you check $# you'll see that $cft->reval( 'no warnings;' . ') 1' ); failed. 'require' trapped by operation mask at (eval 5) line 1.. In other words, Safe is doing its job and preventing that code from trying to load a library.
$cft->reval( 'BEGIN { warnings->unimport; } ) 1' ); would work, presuming warnings is already loaded outside the compartment. However, that won't quiet compile time errors. Unlike eval, reval seems to let them through. Use amon's technique of quieting STDERR.
no warnings suppresses all the warnings the use warnings pragma generates. You would probably want to remove any strictures as well. But severe parsing errors will pop up any way.
If you want to execute any code, no matter how pathological, without any output to STDERR, you should locally modify the signal handler:
{
# I know what I'm doing!
local $SIG{__WARN__} = sub {}; # locally ignore any warnings
eval $code; # catches all "die"
}
or we could reopen STDERR to /dev/null:
{
# I know what I'm doing!
open my $oldSTDERR, '>&' \*STDERR or die;
close STDERR or die;
open STDERR, '>', '/dev/null' or die;
eval $code;
close STDERR or die;
open STDERR, '>&', $oldSTDERR or die;
close $oldSTDERR;
}