Pergunta

Eu tenho uma pergunta geral sobre popen (e todas as funções relacionadas), aplicável a todos os sistemas operacionais, quando eu escrever um script python ou algum código c e executar o executável resultante do console (ganhar ou linux), eu posso imediatamente ver a saída do processo. No entanto, se eu executar o mesmo executável como um processo bifurcada com a sua stdout redirecionado dentro de um tubo, os buffers de saída em algum lugar, geralmente até 4096 bytes antes de ser escrito para o tubo onde o processo pai pode lê-lo.

O seguinte script python irá gerar a saída em pedaços de 1024 bytes

import os, sys, time

if __name__ == "__main__":
     dye = '@'*1024
     for i in range (0,8):
        print dye
        time.sleep(1)

O seguinte script Python irá executar o script anterior e ler a saída, logo que se trata de tubo, byte por byte

import os, sys, subprocess, time, thread

if __name__ == "__main__":
    execArgs = ["c:\\python25\\python.exe", "C:\\Scripts\\PythonScratch\\byte_stream.py"]

    p = subprocess.Popen(execArgs, bufsize=0, stdout=subprocess.PIPE)
    while p.returncode == None:
        data = p.stdout.read(1)
        sys.stdout.write(data)
        p.poll()

Ajustar o caminho para o seu sistema operacional. Quando executado nesta configuração, a saída não será exibido em blocos de 1024, mas pedaços de 4096, apesar do tamanho do buffer do popen conjunto de comandos estar a 0 (que é o padrão de qualquer maneira). Alguém pode me dizer como alterar este comportamento ?, existe alguma maneira eu posso forçar o sistema operacional para tratar a saída do processo bifurcado da mesma maneira como quando ele é executado a partir do console ?, ou seja, apenas alimentar os dados através sem buffer?

Foi útil?

Solução

Em geral, a biblioteca C de tempo de execução padrão (que está sendo executado em nome de praticamente todos os programas em todos os sistemas, mais ou menos ;-) detecta se stdout é um terminal ou não; se não, ele isola a saída (que pode ser um enorme ganho de eficiência, em comparação com a saída sem buffer).

Se você está no controle do programa que está fazendo a escrita, você pode (como uma outra resposta sugerida) nivelada stdout continuamente, ou (mais elegantemente se possível) tentar forçar stdout ser unbuffered, por exemplo, executando Python com a bandeira -u linha de comando:

-u     : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)
         see man page for details on internal buffering relating to '-u'

(o que a página homem acrescenta uma menção de stdin e problemas com o modo binário [s]).

Se você não pode ou não quer tocar o programa que está escrevendo, -u ou similar sobre o programa que está apenas a leitura é improvável que a ajuda (o buffer que mais importa é o que acontece no stdout do escritor, não aquele em stdin do leitor). A alternativa é para enganar o escritor em acreditar que ele está escrevendo a um terminal (embora na verdade ele está escrevendo para outro programa!), Através do módulo de biblioteca padrão pty ou o terceiro nível mais alto pexpect módulo (ou, para Windows, o seu porto wexpect ).

Outras dicas

Isso é corrigir, e se aplica a Windows e Linux (e possivelmente outros sistemas), com popen() e fopen(). Se quiser que o buffer de saída para ser enviada antes de 4096 bytes, o uso fflush() (em C) ou sys.stdout.flush() (Python).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top