направлять большие объемы данных на стандартный ввод при использовании subprocess.Popen

Я как бы изо всех сил пытаюсь понять, как питон решает эту простую проблему.

Моя проблема довольно проста. Если вы используете следующий код, он зависнет. Это хорошо задокументировано в документации модуля подпроцесса.

import subprocess

proc = subprocess.Popen(['cat','-'],
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE,
                        )
for i in range(100000):
    proc.stdin.write('%d\n' % i)
output = proc.communicate()[0]
print output

В поисках решения (есть очень проницательный поток, но я потерял его сейчас), я нашел это решение (среди прочего), в котором используется явная вилка:

import os
import sys
from subprocess import Popen, PIPE

def produce(to_sed):
    for i in range(100000):
        to_sed.write("%d\n" % i)
        to_sed.flush()
    #this would happen implicitly, anyway, but is here for the example
    to_sed.close()

def consume(from_sed):
    while 1:
        res = from_sed.readline()
        if not res:
            sys.exit(0)
            #sys.exit(proc.poll())
        print 'received: ', [res]

def main():
    proc = Popen(['cat','-'],stdin=PIPE,stdout=PIPE)
    to_sed = proc.stdin
    from_sed = proc.stdout

    pid = os.fork()
    if pid == 0 :
        from_sed.close()
        produce(to_sed)
        return
    else :
        to_sed.close()
        consume(from_sed)

if __name__ == '__main__':
    main()

Хотя это решение концептуально очень легко понять, оно использует еще один процесс и застряло на слишком низком уровне по сравнению с модулем подпроцесса (то есть просто для того, чтобы скрыть такие вещи ...).

Мне интересно: есть ли простое и чистое решение, использующее модуль подпроцесса, который выиграл? t завис, или для реализации этого паттерна мне нужно сделать шаг назад и реализовать цикл выбора старого стиля или явную вилку?

Спасибо

15
задан mac 11 December 2011 в 19:51
поделиться