'python how to cleanup a subprocess
I'm running a python script that will restart a subprocess every 2 hours. code as follow.
import datetime
import os
import signal
import subprocess
import sys
import time
if __name__ == '__main__':
while True:
with subprocess.Popen([sys.executable, '/script.py']) as p:
start_time = datetime.datetime.now()
try:
print(f'starting the process at {p.pid}')
p.communicate(timeout=4800)
except subprocess.TimeoutExpired:
print('timeout terminate process')
os.kill(p.pid, signal.SIGINT)
p.terminate()
p.wait(60)
p.kill()
dif = datetime.datetime.now()-start_time
t = 4810-dif.total_seconds()
print(f'restarting after {t/60} mins')
time.sleep(t)
in my script.py, I'm having a thread executor that each thread runs a chrome webdriver instance. The issue I'm having is when the process timeout, the python process is terminated but all the webdriver instances are still lingering. Is there a way for the parent process to kill all the spawned child processes aka the chrome driver instances in my case? Running on my mac
Edit: script.py
def run_with_config(user):
i = WebDriverInstance()
try:
return i.run_loop() # while true infinite loop running some ui actions
except Exception:
return False
finally:
i.quit()
def run(users):
with concurrent.futures.ThreadPoolExecutor(max_workers=len(user_configs)) as executor:
f_to_user = {}
for c in user_configs:
f = executor.submit(run_with_config, c)
f_to_user[f] = c
for f in concurrent.futures.as_completed(f_to_user):
res = f.result()
print(res)
Solution 1:[1]
passing preexec_fn=os.setpgrp
to subprocess popen works for me.
Solution 2:[2]
Run the subprocess in a new process group, then kill the entire group with os.killpg()
.
if __name__ == '__main__':
while True:
with subprocess.Popen([sys.executable, '/script.py'], creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) as p:
start_time = datetime.datetime.now()
try:
print(f'starting the process at {p.pid}')
p.communicate(timeout=4800)
except subprocess.TimeoutExpired:
print('timeout terminate process')
os.killpg(p.pid, signal.SIGINT)
p.terminate()
p.wait(60)
p.kill()
dif = datetime.datetime.now()-start_time
t = 4810-dif.total_seconds()
print(f'restarting after {t/60} mins')
time.sleep(t)
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 | Khalil |
Solution 2 | Barmar |