'Cannot kill a loading animation when using multiprocessing

I'm trying to use multiprocessing to run multiple scripts. At the start, I launch a loading animation, however I am unable to ever kill it. Below is an example...

Animation: foo.py

import sys
import time
import itertools

# Simple loading animation that runs infinitely.
for c in itertools.cycle(['|', '/', '-', '\\']):
    sys.stdout.write('\r' + c)
    sys.stdout.flush()
    time.sleep(0.1)

Useful script: bar.py

from time import sleep
# Stand-in for a script that does something useful.
sleep(5)

Attempt to run them both:

import multiprocessing
from multiprocessing import Process
import subprocess

pjt_dir = "/home/solebay/path/to/project" # Setup paths..
foo_path = pjt_dir + "/foo.py" # ..
bar_path = pjt_dir + "/bar.py" # ..

def run_script(path): # Simple function that..
    """Launches python scripts.""" # ..allows me to set a.. 
    subprocess.run(["python", path]) # ..script as a process.

foo_p = Process(target=run_script, args=(foo_path,)) # Define the processes..
bar_p = Process(target=run_script, args=(bar_path,)) # ..

foo_p.start() # start loading animation
bar_p.start() # start 'useful' script 

bar_p.join() # Wait for useful script to finish executing
foo_p.kill() # Kill loading animation

I get no error messages, and (my_venv) solebay@computer:~$ comes up in my terminal, but the loading animation persists (clipping over my name and environement). How can I kill it?



Solution 1:[1]

I've run into a similar situation before where I couldn't terminate the program using ctrl + c. The issue is (more or less) solved by using daemonic processes/threads (see multiprocessing doc). To do this, you simply change

foo_p = Process(target=run_script, args=(foo_path,)) 

to

foo_p = Process(target=run_script, args=(foo_path,), daemon=True) 

and similarly for other children processes that you would like to create.

With that being said, I myself am not exactly sure if this is the correct way to remedy the issue with not being able to terminate the multiprocessing program, or is it just some artifact that happens to help with this. I would suggest this thread that went into the discussion about daemon threads more. But essentially, from my understanding, daemon threads would be terminated automatically whenever their parent process is terminated, regardless of whether they are finished or not. Meanwhile, if a thread is not daemonic, then somehow you need to wait until the children processes to finish before you're able to fully terminate the program.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Remy Lau