Python 子进程popen实时输出超时
经过一些研究,我一直在使用subprocess.check_output(),它接受timeout参数,并在达到命令超时时引发TimeoutExpired。没关系,但限制是我无法获得实时输出,因此我被迫直接使用Popen,基本上:Python 子进程popen实时输出超时,python,python-3.x,subprocess,Python,Python 3.x,Subprocess,经过一些研究,我一直在使用subprocess.check_output(),它接受timeout参数,并在达到命令超时时引发TimeoutExpired。没关系,但限制是我无法获得实时输出,因此我被迫直接使用Popen,基本上: def execute_cmd(cmd, timeout=2): p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) for l
def execute_cmd(cmd, timeout=2):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
print(line.rstrip().decode("utf-8"))
p.stdout.close()
retcode = p.wait()
如何在这段代码中添加超时?我终于想出了一个计时器解决方案。不确定这是不是最好的方法,但它是有效的
import os
import signal
import subprocess
import time
from threading import Timer
def execute_bash_cmd(cmd, timeout=5):
print("cmd: " + cmd)
def timerout(p):
print("Command timed out")
timer.cancel()
os.killpg(os.getpgid(p.pid), signal.SIGTERM)
# or use p.kill() if shell==False
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
timer = Timer(timeout, timerout, args=[p])
timer.start()
for line in iter(p.stdout.readline,b''):
line = line.rstrip().decode("utf-8")
print(line)
p.stdout.close()
retcode = p.wait()
timer.cancel()
示例:
execute_bash_cmd('ls -l /')
execute_bash_cmd('sleep 2', 3)
execute_bash_cmd('sleep 4', 3)
输出:
cmd: ls -l /
total 92
drwxr-xr-x 2 root root 4096 Feb 18 15:28 bin
drwxr-xr-x 3 root root 4096 Feb 18 15:16 boot
drwxr-xr-x 20 root root 4020 Feb 18 15:43 dev
drwxr-xr-x 134 root root 12288 Feb 19 22:42 etc
drwxr-xr-x 3 root root 4096 Jun 7 2018 home
drwxr-xr-x 7 root root 4096 Feb 18 15:28 lib
drwxr-xr-x 5 root root 4096 Feb 18 15:28 lib64
drwx------ 2 root root 16384 Feb 18 13:12 lost+found
drwxr-xr-x 2 root root 4096 Jun 7 2018 mnt
drwxr-xr-x 3 root root 4096 Feb 18 15:26 opt
dr-xr-xr-x 247 root root 0 Feb 18 15:43 proc
drwx------ 10 root root 4096 Feb 19 22:42 root
drwxr-xr-x 37 root root 1060 Feb 19 20:21 run
drwxr-xr-x 2 root root 12288 Feb 18 15:20 sbin
drwxr-xr-x 2 root root 4096 Jun 7 2018 selinux
drwxr-xr-x 5 root root 4096 Feb 18 15:18 srv
dr-xr-xr-x 13 root root 0 Feb 19 22:42 sys
drwxrwxrwt 23 root root 4096 Feb 19 22:37 tmp
drwxr-xr-x 11 root root 4096 Jun 7 2018 usr
drwxr-xr-x 11 root root 4096 Feb 18 14:15 var
cmd: sleep 2
cmd: sleep 4
Command timed out
Terminated
你说的“我没有得到实时输出”是什么意思?当命令执行完毕时,输出被打印出来。如果需要5分钟,我必须等到最后才能看到完整的输出。我想要类似于这个例子的东西,在这里我可以“实时”提取输出。听起来你(也?)需要一个带超时的
读线。无论如何,由于进程间通信的性质,我怀疑这是否可以“实时”完成。此外,以非特定于平台的方式执行此操作也可能非常复杂,子流程模块的性能就是明证。至少,我希望看到的输出就像我在手动运行命令一样。因此,无需等待subprocess.run()/check_output()完成。