Python 使用其他进程的标准输出(使用Popen创建)

Python 使用其他进程的标准输出(使用Popen创建),python,subprocess,popen,Python,Subprocess,Popen,我想计算使用Popen创建的进程(此处为unar.exe)写入stdout的行数 import time from subprocess import Popen, PIPE, STDOUT p = Popen('unrar.exe x -y myfile.rar', stdout=PIPE) while (p is not finished): # pseudo code here and next lines... time.sleep(0.100) print

我想计算使用
Popen
创建的进程(此处为unar.exe)写入
stdout
的行数

import time
from subprocess import Popen, PIPE, STDOUT

p = Popen('unrar.exe x -y myfile.rar', stdout=PIPE)

while (p is not finished):      # pseudo code here and next lines...
    time.sleep(0.100)
    print 'Number of lines written to STDOUT by unrar' + len(PIPE.split('\n'))
如何正确执行此操作?


备注:我已经看过了
p.communicate()
(),但这会阻止Python的执行,直到
p
终止,这不是我想要的:我想能够在运行时打印
p
写入的行数。

我不知道这是否是最干净的方法,但它是有效的:

from subprocess import Popen, PIPE
import io, time

p = Popen('unrar.exe x -y myfile.rar', stdout = PIPE)

b = ' '
i = 0 
while b:
    b = p.stdout.readline()
    i += 1
    print i

print 'FINISHED'    
我正在寻找一个更简单的解决方案,不使用其他线程,等等。我不介意进程是否每100毫秒被阻塞一次


如果进程不能阻塞是一个硬要求,那么您需要线程(或其他异步技术)。为了模拟非阻塞
wc——可能重复@MartijnPieters的行,我正在寻找一种更简单的解决方案,而不使用其他线程,等等。我不介意进程是否每100行阻塞一次ms@Basj:除非使用threads或
select
poll
kqueue
,Windows上的命名管道),否则无法在不阻塞的情况下执行此操作或
fcntl
或类似文件。@J.F.Sebastian:在哪种情况下可以在
readline()处阻止它?如果没有更多的行,它不会给出
'
,然后循环不会结束吗?
p.stdout.readline()
阻塞直到一行可用或EOF,例如,在一个典型的情况下,块缓冲输出到一个管道,直到管道缓冲区溢出或刷新为止,您不会看到任何东西(打印当前时间,以查看父进程是否可以看到突发的输出)。如果子进程没有产生太多输出,则可能需要一段时间才能看到第一行。
#!/usr/bin/env python
import io
import shlex
from functools import partial
from subprocess import Popen, PIPE
from threading import Thread
from Queue import Queue

def count_lines(pipe, queue, chunksize=io.DEFAULT_BUFFER_SIZE):
    #NOTE: you could write intermediate results here (just drop `sum()`)
    queue.put(sum(chunk.count(b'\n')
                  for chunk in iter(partial(pipe.read, chunksize), b'')))
    pipe.close()

p = Popen(shlex.split('unrar.exe x -y myfile.rar'), stdout=PIPE, bufsize=-1)
result = Queue()
Thread(target=count_lines, args=[p.stdout, result]).start()
p.wait() # you can omit it if you want to do something else and call it later
number_of_lines = result.get() # this blocks (you could pass `timeout`)
#!/usr/bin/env python
import shlex
from subprocess import Popen, PIPE

p = Popen(shlex.split('unrar.exe x -y myfile.rar'), stdout=PIPE, bufsize=1)
count = 0
for line in iter(p.stdout.readline, b''):
    count += 1
    print count
p.stdout.close()
p.wait()