您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Python子进程杀死超时

Python子进程杀死超时

该文档明确指出应终止该进程:

文档中获取subprocess.run

“ timeout参数传递给Popen.communicate()。如果超时到期,子进程将被杀死并等待。子进程终止后,将重新引发TimeoutExpired异常。”

但是在您的情况下,您正在使用shell=True,而且我之前也遇到过类似的问题,因为阻塞过程是Shell过程的子过程。

我认为,shell=True如果适当地分解参数并且脚本具有适当的shebang,则不需要。您可以尝试以下方法

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上非常轻松地重现此问题(使用Popen,但这是同一回事):

import subprocess,time

p=subprocess.Popen("notepad",shell=True)
time.sleep(1)
p.kill()

=>记事本保持打开状态,可能是因为它设法脱离了父shell进程。

import subprocess,time

p=subprocess.Popen("notepad",shell=False)
time.sleep(1)
p.kill()

=>记事本在1秒后关闭

有趣的是,如果将其删除time.sleep()kill()即使shell=True可能成功杀死正在启动的外壳,它也可以正常工作notepad

我并不是说您有完全相同的问题,我只是shell=True出于多种原因证明这是邪恶的,而无法中止/超时则是另一个原因。

但是, 如果 你需要shell=True一个理由,你可以使用psutil杀到底所有的孩子。在这种情况下,最好使用它,Popen以便直接获取进程ID:

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 2022/1/1 18:39:06 有251人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶