个人电脑系统:Ubuntu18.04
Python版本:3.6.9
当子进程执行类似“adb logcat”的命令时。Popen,我想获取标准输出,并根据其中的关键字决定是否停止子进程。
如果关键字长时间不出现,我也会停止。第一次尝试如下
import time
import subprocess
cmd = "adb logcat"
timeout = 10
adb_shell_pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, universal_newlines=True)
start_time = time.time()
for info in iter(adb_shell_pipe.stdout.readline, ""):
if "keyword" in info:
print("Find keyword!")
# Omit kill process
break
if time.time() - start_time > timeout:
print("Fail!")
# Omit kill process
break
代码成功地完成了我需要的工作,但我发现,如果在子进程启动后的第10秒没有下一个输出,程序将不会以“Fail!”结束直到下一次输出。
我想是因为
readline()
块来读取输出。因此,我将stdout设置为non block by
fcntl
比如下面的代码
import os
import time
import fcntl
import subprocess
# Command was replaced to create test scenarios
cmd = "adb shell"
timeout = 10
adb_shell_pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, universal_newlines=True)
fd = adb_shell_pipe.stdout.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
count = 0
start_time = time.time()
while adb_shell_pipe.poll() is None:
count += 1
info = adb_shell_pipe.stdout.readline()
if info and "keyword" in info:
print("Find keyword!")
# Omit kill process
break
if time.time() - start_time > timeout:
print("Fail!")
# Omit kill process
break
print(count)
# Output
Fail!
4131304
如上所示,结果与预期一致。然而,它会执行
readline()
10秒内4131304次,可能会浪费资源
文件锁
模块不能在Windows上使用。
那么,有没有一种更优雅、更通用的方法来实现这个需求呢?