This article mainly introduces the capture warning information in Perl, exception information and write to the log in detail, this article gives the capture warning-not processing, catch warning-and converted to exceptions, catch warnings-and write logs, capture and write a complete example of the log, and other practical examples, the need for friends can refer to the
Although it is recommended that you turn on warnings in every Perl script and module, you do not want users to see a warning from Perl.
On the one hand you want to use using warnings as your safety net in front of the code, on the other hand, warnings will appear on the screen. In most cases, customers do not know how to handle these warnings. If you're lucky, these warnings just surprise the customer, and of course, unfortunately they try to fix them ... (This isn't about Perl programmers.) )
Third, you may want to save these warnings for later analysis.
In addition, there are many Perl scripts and applications that are not using use warnings and not using-W in #! rows. Adding a use warnings may produce a large number of warnings.
In the long run, it is of course to dispel these warnings, but in the short term?
Even in a long-term plan, you can't write code that has no bugs at all, and you can't be sure that the application will never print out a warning message.
Can you?
You can capture the warnings before they are printed to the screen.
Signal
Perl has a built-in hash table called%sig, where the key is the name of the operating system signal. The corresponding values are functions (mostly function references) that are invoked when a particular signal is triggered.
In addition to the standard signals provided by the system, Perl added two internal "signals." One of them is
In this article, we'll see how these affect the warning message.
anonymous functions
Sub {} is an anonymous function, which is a function that has no name but a function body. (In this case, the function body is also empty, but I hope you understand what I mean.) )
Catch warning-do not process
If you add the following code:
The code is as follows:
Local $SIG {__warn__} = sub {
# Here you can get a warning message
};
This actually means that whenever a warning message is generated somewhere in the program, no processing is done. Basically, this hides all the warnings.
Catch warning--and convert to exception
Could also write: You can also write:
The code is as follows:
Local $SIG {__warn__} = sub {
Die
};
This invokes die () each time a warning is generated, which translates each warning into an exception.
If you want to include a warning message in an exception, you can write this:
The code is as follows:
Local $SIG {__warn__} = sub {
my $message = shift;
Die $message;
};
The actual warning message is passed to the anonymous function as a unique parameter.
Capturing warnings-and writing to logs
You might want to do something else in the middle:
Filter noisy warning messages for later analysis:
The code is as follows:
Local $SIG {__warn__} = sub {
my $message = shift;
Logger ($message);
};
Here we assume that logger () is the write-log function you implement.
Write log
Let's say your application already has a logging mechanism. If not, it would be better to add. Even if you can't add, you need the built-in log mechanism for the operating system. For example, Linux's syslog,ms Windows event Logger, other operating systems also have their internal logging mechanism.
In the example of this article, we use a self-made logger () function to represent this idea.
Complete example of capturing and writing logs
The code is as follows:
#!/usr/bin/perl
Use strict;
Use warnings;
Local $SIG {__warn__} = sub {
my $message = shift;
Logger (' warning ', $message);
};
My $counter;
Count ();
print "$countern";
Sub Count {
$counter = $counter + 42;
}
Sub Logger {
My ($level, $msg) = @_;
if (open my $out, ' >> ', ' Log.txt ') {
Chomp $msg;
Print $out "$level-$MSGN";
}
}
The above code adds the following line to the Log.txt file:
The code is as follows:
Use the uninitialized value in addition (+) at code_with_warnings.pl Line 14.
The variable $counter and the function count () are only part of the alert notification example.
Warning messages in the warning handler function
__WARN__ is automatically disabled during the execution of its handler function. Therefore, the (new) warning message generated during the execution of the warning handler function does not cause an infinite loop.
You can learn more about the details in the Perlvar document.
Avoid multiple warnings
Note that duplicate warning messages may flood the log files. I can use a simple caching-like feature to reduce the number of repetitive warning messages.
The code is as follows:
#!/usr/bin/perl
Use strict;
Use warnings;
My%warns;
Local $SIG {__warn__} = sub {
my $message = shift;
return if $WARNS {$message}++;
Logger (' warning ', $message);
};
My $counter;
Count ();
print "$countern";
$counter = undef;
Count ();
Sub Count {
$counter = $counter + 42;
}
Sub Logger {
My ($level, $msg) = @_;
if (open my $out, ' >> ', ' Log.txt ') {
Chomp $msg;
Print $out "$level-$MSGN";
}
}
As you can see, we assign the $counter variable to undef, and then call the count () function again to produce the same warning.
We also replaced __warn__ 's handler function with a slightly more complex version:
The code is as follows:
My%warns;
Local $SIG {__warn__} = sub {
my $message = shift;
return if $WARNS {$message}++;
Logger (' warning ', $message);
};
Before calling logger, check to see if the current string is already in the%warnshash table. If not, it is added and the logger () is invoked. If it is already there, call return and do not record the same event two times.
You may recall that we used the same idea in the unique values in an array.
What is local?
In all of the above examples, I use the local function to localize (warning processing) effects. Strictly speaking, we do not need to do this in these examples, as it is assumed that the code is the first part of the main script. In this case, it doesn't matter, after all, it's in the global scope.
However, it is best to use this.
It is important for local changes in the module to limit (to warnings). In particular, the module to be published. If not localized, the entire application is affected. Limit limits the impact to the closed code block in which it is located.
Avoid using the global%warns
If you are using Perl 5.10 or newer versions, you can rewrite the code to replace the global variable%warns. To do this, use the using v5.10 at the beginning of the script, and then use the state keyword inside the anonymous function to declare the variable.
The code is as follows:
#!/usr/bin/perl
Use strict;
Use warnings;
Use v5.10;
Local $SIG {__warn__} = sub {
State%warns;
my $message = shift;
return if $WARNS {$message}++;
Logger (' warning ', $message);
};