Usando subprocesso com select e pty trava ao capturar saída

Eu estou tentando escrever um programa python que é capaz de interagir com outros programas. Isso significa enviar stdin e receber dados stdout. Eu não posso usar pexpect (embora definitivamente inspirou um pouco do design). O processo que estou usando agora é o seguinte:

Anexar um pty ao stdout do subprocessoRealce até que o subprocesso saia verificandosubprocess.pollQuando houver dados disponíveis no stdout, escreva esses dados imediatamente no stdout atual.Terminar!

Eu tenho prototipado algum código (abaixo) que funciona, mas parece ter uma falha que está me incomodando. Depois que o processo filho for concluído, o processo pai será interrompido se eu não especificar um tempo limite ao usarselect.select. Eu realmente preferiria não definir um tempo limite. Parece um pouco sujo. No entanto, todas as outras maneiras que eu tentei contornar o problema não parecem funcionar. Pexpect parece contornar isso usandoos.execv epty.fork ao invés desubprocess.Popen epty.openpty uma solução que eu não prefiro. Estou fazendo algo errado com a forma de verificar a vida do subprocesso? Minha abordagem está incorreta?

O código que estou usando está abaixo. Eu estou usando isso em um Mac OS X 10.6.8, mas eu preciso que ele funcione no Ubuntu 12.04 também.

Este é o corredor do subprocessorunner.py:

import subprocess
import select
import pty
import os
import sys

def main():
    master, slave = pty.openpty()

    process = subprocess.Popen(['python', 'outputter.py'], 
            stdin=subprocess.PIPE, 
            stdout=slave, stderr=slave, close_fds=True)

    while process.poll() is None:
        # Just FYI timeout is the last argument to select.select
        rlist, wlist, xlist = select.select([master], [], [])
        for f in rlist:
            output = os.read(f, 1000) # This is used because it doesn't block
            sys.stdout.write(output)
            sys.stdout.flush()
    print "**ALL COMPLETED**"

if __name__ == '__main__':
    main()

Este é o código do subprocessooutputter.py. As partes aleatórias estranhas são apenas para simular um programa que envia dados em intervalos aleatórios. Você pode removê-lo se desejar. Não deveria importar:

import time
import sys
import random

def main():
    lines = ['hello', 'there', 'what', 'are', 'you', 'doing']
    for line in lines:
        sys.stdout.write(line + random.choice(['', '\n']))
        sys.stdout.flush()
        time.sleep(random.choice([1,2,3,4,5])/20.0)
    sys.stdout.write("\ndone\n")
    sys.stdout.flush()

if __name__ == '__main__':
    main()

Obrigado por qualquer ajuda que todos possam fornecer!

Nota extra

pty é usado porque quero garantir que a stdout não esteja em buffer.

questionAnswers(4)

yourAnswerToTheQuestion