使用其他进程的stdout(使用Popen创建)

时间:2014-02-24 13:32:56

标签: python subprocess popen

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

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()https://python.readthedocs.org/en/v2.7.2/library/subprocess.html#subprocess.Popen.communicate),但这会阻止执行Python,直到p终止,不是我想要的:我希望能够在p运行时打印{{1}}所写的行数。

2 个答案:

答案 0 :(得分:1)

  

我正在寻找一个更简单的解决方案而不使用其他线程等。我不介意这个过程是否每100毫秒被阻止

如果要求进程不能阻塞,则需要线程(或其他异步技术)。要模仿非阻塞wc --lines <(cmd)

#!/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`)

另一方面,如果你只需要“来打印p写的行数 运行。“然后你可以计算主线程中的行数:

#!/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()

答案 1 :(得分:0)

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

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'