pel*_*zza 5 python parsing subprocess pexpect output
我正在尝试实时解析块缓冲程序的输出,这意味着直到进程结束才可用。我需要的只是逐行解析,过滤和管理输出中的数据,因为它可能要运行数小时。
我试图用subprocess.Popen()捕获输出,但是是的,正如您可能猜到的那样,Popen无法管理这种行为,它会一直缓冲直到过程结束。
from subprocess import Popen, PIPE
p = Popen("my noisy stuff ", shell=True, stdout=PIPE, stderr=PIPE)
for line in p.stdout.readlines():
#parsing text and getting data
Run Code Online (Sandbox Code Playgroud)
因此,我发现了pexpect,它可以实时输出输出,因为它将stdout视为文件,或者我什至可以做一个肮脏的技巧来打印文件并在函数外部解析它。但是好吧,即使对于我来说,它也太脏了;)
import pexpect
import sys
pexpect.run("my noisy stuff", logfile=sys.stdout)
Run Code Online (Sandbox Code Playgroud)
但我想这应该是一种更好的pythonic方式,只需像子进程一样管理stdout。普朋呢。我怎样才能做到这一点?
编辑:
运行JF提案:
这是故意的错误审核,大约需要25秒。停止。
from subprocess import Popen, PIPE
command = "bully mon0 -e ESSID -c 8 -b aa:bb:cc:dd:ee:00 -v 2"
p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE)
for line in iter(p.stdout.readline, b''):
print "inside loop"
print line
print "outside loop"
p.stdout.close()
p.wait()
#$ sudo python SCRIPT.py
### <= 25 secs later......
# inside loop
#[!] Bully v1.0-21 - WPS vulnerability assessment utility
#inside loop
#[!] Using 'ee:cc:bb:aa:bb:ee' for the source MAC address
#inside loop
#[X] Unable to get a beacon from the AP, possible causes are
#inside loop
#[.] an invalid --bssid or -essid was provided,
#inside loop
#[.] the access point isn't on channel '8',
#inside loop
#[.] you aren't close enough to the access point.
#outside loop
Run Code Online (Sandbox Code Playgroud)
使用此方法代替:编辑:由于输出中的大量延迟和超时,我不得不修复该子项,并添加了一些技巧,因此最终代码如下所示
import pexpect
child = pexpect.spawn(command)
child.maxsize = 1 #Turns off buffering
child.timeout = 50 # default is 30, insufficient for me. Crashes were due to this param.
for line in child:
print line,
child.close()
Run Code Online (Sandbox Code Playgroud)
返回相同的输出,但是它实时打印行。所以...解决了感谢@JF Sebastian
.readlines()读取所有行。难怪在子进程结束之前您看不到任何输出。您可以.readline()在子进程刷新其标准输出缓冲区后立即逐行读取:
from subprocess import Popen, PIPE
p = Popen("my noisy stuff", stdout=PIPE, bufsize=1)
for line in iter(p.stdout.readline, b''):
# process line
..
p.stdout.close()
p.wait()
Run Code Online (Sandbox Code Playgroud)
如果您已经有了,pexpect那么您可以使用它来解决块缓冲问题:
import pexpect
child = pexpect.spawn("my noisy stuff", timeout=None)
for line in child:
# process line
..
child.close()
Run Code Online (Sandbox Code Playgroud)
另请参阅我在评论中链接的问题中stdbuf基于pty, - 的解决方案。