inn*_*ree 11 python subprocess
我想在子进程上使用超时
from subprocess32 import check_output
output = check_output("sleep 30", shell=True, timeout=1)
Run Code Online (Sandbox Code Playgroud)
不幸的是,虽然这会引发超时错误,但它会在30秒后发生.似乎check_output不能中断shell命令.
我可以在Python端做些什么来阻止它?我怀疑subprocess32无法终止超时进程.
jfs*_*jfs 25
with Popen(*popenargs, stdout=PIPE, **kwargs) as process:
try:
output, unused_err = process.communicate(inputdata, timeout=timeout)
except TimeoutExpired:
process.kill()
output, unused_err = process.communicate()
raise TimeoutExpired(process.args, timeout, output=output)
Run Code Online (Sandbox Code Playgroud)
有两个问题:
.communicate()可能等待后代进程,而不仅仅是直接子进程,请参阅Python子进程.check_call vs .check_outputprocess.kill()可能不会杀死整个进程树,请参阅如何终止使用shell = True启动的python子进程它会导致您观察到的行为:TimeoutExpired在一秒钟内发生,shell被终止,但check_output()仅在孙子sleep进程退出后30秒内返回.
要解决问题,请终止整个进程树(属于同一组的所有子进程):
#!/usr/bin/env python3
import os
import signal
from subprocess import Popen, PIPE, TimeoutExpired
from time import monotonic as timer
start = timer()
with Popen('sleep 30', shell=True, stdout=PIPE, preexec_fn=os.setsid) as process:
try:
output = process.communicate(timeout=1)[0]
except TimeoutExpired:
os.killpg(process.pid, signal.SIGINT) # send signal to the process group
output = process.communicate()[0]
print('Elapsed seconds: {:.2f}'.format(timer() - start))
Run Code Online (Sandbox Code Playgroud)
Elapsed seconds: 1.00
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9590 次 |
| 最近记录: |