-
-
Save jizhilong/6687481 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python | |
import multiprocessing | |
import time | |
import subprocess, os, signal, sys | |
def test(s): | |
while True: | |
print s | |
time.sleep(1.5) | |
def kill_child_processes(signum, frame): | |
parent_id = os.getpid() | |
ps_command = subprocess.Popen("ps -o pid --ppid %d --noheaders" % parent_id, shell=True, stdout=subprocess.PIPE) | |
ps_output = ps_command.stdout.read() | |
retcode = ps_command.wait() | |
for pid_str in ps_output.strip().split("\n")[:-1]: | |
os.kill(int(pid_str), signal.SIGTERM) | |
sys.exit() | |
if __name__ == '__main__': | |
pool = multiprocessing.Pool(processes=4) | |
result = pool.map_async(test, 'abcd') | |
signal.signal(signal.SIGTERM, kill_child_processes) | |
result.get(10000) | |
pool.close() | |
pool.join() |
@brando90 you can use psutil
and the following code to create a self-cleaning process:
from contextlib import contextmanager
import subprocess
import psutil
@contextmanager
def process(*args, **kwargs):
proc = subprocess.Popen(*args, **kwargs)
try:
yield proc
finally:
for child in psutil.Process(proc.pid).children(recursive=True):
child.kill()
proc.kill()
Note that the *args, **kwargs
means that process
has the same API as subprocess.Popen
😄
Then you can do:
with process(['mycommand', 'myarg', '--myoption', 'myoptionvalue'], stdout=open('myfile.out.log', 'w')) as proc:
print(proc.pid)
0/0 # even though this throws an exception, the `process` contextmanager will *still* clean up the process correctly
@pcattori impressive usage of contextmanager
and psutil
👍
os.killpg(os.getpid(), signal.SIGTERM)
os.killpg(os.getpid(), signal.SIGTERM)
Best Solution! thanks!
@pcattori impressive usage of contextmanager and psutil 👍
I second that, thank you very much for sharing this, Pedro. We just added your code snippet to a little package we are currently gardening, to make it reusable by others, see pyveci/pueblo#39. We hope you don't have any objections about it. It was the last addition amongst a few updates happening last month, so it just become part of pueblo-0.0.4, also available on PyPI.
I don't get it, why is the code for something so conceptually simple so complicated?