Python subprocess kill with timeout
我正在使用python中的子进程模块运行一些shell脚本。 如果shell脚本运行得很长,我喜欢杀死子进程。 我认为如果我将
这是代码:
1 2 3 4 5 6 7 8 9 10 11 | try: result=run(['utilities/shell_scripts/{0} {1} {2}'.format( self.language_conf[key][1], self.proc_dir, config.main_file)], shell=True, check=True, stdout=PIPE, stderr=PIPE, universal_newlines=True, timeout=30, bufsize=100) except TimeoutExpired as timeout: |
我用一些运行120s的shell脚本测试了这个调用。 我预计子进程会在30秒后被杀死,但实际上这个过程正在完成120s脚本,而不是引发超时异常。 现在问题如何通过超时杀死子进程?
文档明确指出应该杀死进程:
来自
"The timeout argument is passed to Popen.communicate(). If the timeout expires, the child process will be killed and waited for. The TimeoutExpired exception will be re-raised after the child process has terminated."
但是在你的情况下,你正在使用
如果你正确地分解你的论点并且你的脚本有适当的shebang,我认为你不需要
1 2 3 4 5 6 7 8 9 | result=run( [os.path.join('utilities/shell_scripts',self.language_conf[key][1]), self.proc_dir, config.main_file], # don't compose argument line yourself shell=False, # no shell wrapper check=True, stdout=PIPE, stderr=PIPE, universal_newlines=True, timeout=30, bufsize=100) |
请注意,我可以在Windows上轻松地重现此问题(使用
1 2 3 4 5 | import subprocess,time p=subprocess.Popen("notepad",shell=True) time.sleep(1) p.kill() |
=>记事本保持打开状态,可能是因为它设法从父shell进程中分离出来。
1 2 3 4 5 | import subprocess,time p=subprocess.Popen("notepad",shell=False) time.sleep(1) p.kill() |
=>记事本在1秒后关闭
有趣的是,如果你删除
我并不是说你有完全相同的问题,我只是在证明
但是,如果由于某种原因需要
1 2 3 4 5 6 7 8 9 10 11 12 13 | import subprocess,time,psutil parent=subprocess.Popen("notepad",shell=True) for _ in range(30): # 30 seconds if parent.poll() is not None: # process just ended break time.sleep(1) else: # the for loop ended without break: timeout parent = psutil.Process(parent.pid) for child in parent.children(recursive=True): # or parent.children() for recursive=False child.kill() parent.kill() |
(来源:如何从python中杀死进程和子进程?)
该示例也会杀死记事本实例。