Search code examples
pythonbashinterrupt-handlinggnu-parallelraise

How to Raise KeyboardInterrupt to Python Scripts After Interrupting GNU Parallel?


I'm using GNU Parallel to run a Python script for a list of different arguments. Inside the Python script, I'm writing data to a file (in fact, the name of the file is the script argument). The Python script writes the data to the file after processing N trials, where N is another argument. Consequently, the data does not get written until all trials are finished. But the time to go through a trial can vary depending on a number of test arguments. For this reason, should the script take too long for a certain set of arguments, the script allows me to raise a KeyboardInterrupt error (Ctrl+C) and write the data it has obtained so far before terminating.

However, by using GNU Parallel, using Ctrl+C will kill the parallel command, and completely stop the Python jobs, hence no data-so-far being written.

Is it possible to raise KeyboardInterrupt in these Python scripts to have them finish handling the error before parallel is killed? Ideally, it would go something like 1. Execute parallel python script.py ::: args, 2. After an amount of time, cancel using Ctrl+C, 3. Parallel tells Python scripts to see a KeyboardInterrupt (or any error, it doesn't matter) and Parallel pauses to wait for Python jobs to finish handling, 4. Parallel terminates, 5. I have files with the data obtained in that time.

Note: I would like an answer that doesn't ask to rewrite the Python script's data writing method.


Solution

  • I believe you are looking for --termseq. myprog.pl:

    #!/usr/bin/perl
    
    $SIG{'TERM'} = sub { print "TERM received. Flush files.\n"; sleep(1); };
    
    sleep(100);
    

    Now run:

    parallel --termseq TERM,2000,KILL,20 -u ./myprog.pl ::: 1 2 3
    

    When GNU Parallel receives ctrl-c it will send SIGTERM to the child, wait 2000 ms and if the child is still alive kill the child.

    Wait a few seconds and press ctrl-c

    If you are absolutely sure the Python program will exit after receiving the SIGTERM then you can remove ,KILL,20. It is just a fall back if the Python program is stuck for some reason.