python调用shell脚本超时自动杀掉_Python子进程使用超时终止

文档明确指出应该杀死进程:

“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.”

但是在你的情况下你使用的是shell = True,之前我已经看过类似的问题,因为阻塞过程是shell进程的子进程.

如果你正确地分解你的参数并且你的脚本有适当的shebang,我认为你不需要shell = True.你可以试试这个:

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,因为它成功杀死了启动记事本的shell.

我并不是说你有完全相同的问题,我只是在证明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()

该示例也会杀死记事本实例.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值