
Have you ever asked someone to do something for you ... a long task, and you would like a progress report? "How are you getting on?" you'll ask ... and they'll give you an update - "I'm 75% of the way through" they'll say or - perhaps even more helpfully - "I'm nearly there, and I have some good results coming through" or "this is taking a long time and isn't looking very productive".
Such feedback can be very valuable - it can allow you to plan your next stage, it may allow you to start working already with intermediate results ... or it can give you the options to say "as it's not working out, let's try something else a bit more productive instead / let's not waste time finishing that job".
Can you say "how are you getting on" to a long running Perl program? If you have written the program accept such requests then, yes, you can!
Perl uses signals in the
%SIG hash. There are a whole series of external signals that a program can react to including (for the example I wrote during this week's Perl course) ^C (Control - C) which is in
$SIG{INT}.
When you want to set up a signal processor, so that you override the default action, simply put the name of the new handler
as a text string into the %SIG hash:
$SIG{INT} = "hello";
Then - whenever ^C is pressed - the sub called
hello will be run.
But before you go off and write a long and exciting piece of code in the sub, remember that you can't control your user - (s)he could press ^C at any subsequent point in your program, and cause the extra piece of code to be run at ANY time; that could be in the middle of a loop, it could be between a series of statements that update a database, or at any other inconvenient time where your data / variables / stack are in a transient state. So - please keep your signal handler routine really simple - I usually just set a global variable to a known value (such as "1" to know I have the signal set); I can then check that variable at the end of an iteration / known points in my code, where I generate a status report based on stable conditions, I reset the flag variable, and carry on.
So:
sub hello {
$ish = 1;
}
and at the end of my main code loop (after processing the next one of millions of records, perhaps):
if ($ish) {
print ("$s_x $s_p $s_b\n");
$ish = 0;
}
But what if I *really* want to abort my program? Well - I've got a little trick. I make a note of the time that ^C is pressed, and if it's pressed twice within 3 seconds, I sense that my user is getting impatient and I exit from the process ;-). Here's my modified
sub hello
sub hello {
$ish = 1;
$when = time();
if ($when - $previous < 3) {
die("Exiting - multiple ^C\n");
}
$previous = time();
}
The subject is taught on our
Perl for Larger Projects course. And also (where it's appropriate, as it was this week) on private Perl courses run for single organizations.
It's implemented within a complete example - at
[here], where I was combining 2 files of over 100 Mbytes each, matching up corresponding records, prior to analyzing them.
Further examples from our course material directories ...
Testing with just a sample of data (truncating the run)
[here].
A demonstration with good intermediate user feedback (progress bar with info type)
[here].
Asking for intermediate results via signals -
[here] and
[here]
Illustration - delegates on the Perl course which inspired this example and blog
(written 2010-06-13, updated 2010-06-18)
Associated topics are indexed as below, or enter http://melksh.am/nnnn for individual articles
P667 - Perl - Handling Huge Data [639] Progress bars and other dynamic reports - (2006-03-09)
[762] Huge data files - what happened earlier? - (2006-06-15)
[975] Answering ALL the delegate's Perl questions - (2006-12-09)
[1397] Perl - progress bar, supressing ^C and coping with huge data flows - (2007-10-20)
[1920] Progress Bar Techniques - Perl - (2008-12-03)
[1924] Preventing ^C stopping / killing a program - Perl - (2008-12-05)
[2376] Long job - progress bar techniques (Perl) - (2009-08-26)
[2806] Macho matching - do not do it! - (2010-06-13)
[2834] Teaching examples in Perl - third and final part - (2010-06-27)
[3374] Speeding up your Perl code - (2011-07-30)
[3375] How to interact with a Perl program while it is processing data - (2011-07-31)
Some other Articles
Frankfurt in 90 minutesFrom home to Nurnberg - journey picturesCanal through Melksham - the options and issuesHow are you getting on?Regular Expression MythsTravelling across EuropeAfter the Perl course in NurnbergBinary data handling with unpack in PerlThe Merchants And