Obtendo stdin de um pipe nomeado

10

O que eu estou tentando fazer é executar python em uma janela de terminal e redirecionar seu stdin de um pipe nomeado. Então eu escrevo para o pipe nomeado em outro terminal e tenho esse comando executado em python.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

echo -n "print \"Hello World\"" > p1

O que acontece é que - o python imprime Hello World e sai. O que eu quero fazer é manter o Python rodando para pegar o próximo comando. Como faço isso no shell?

    
por Lord Loh. 19.04.2013 / 05:06

4 respostas

10

Você precisa

  • Execute o python interativamente, mesmo que seu stdin não seja um terminal: use python -i
  • mantenha o fim da escrita do pipe aberto; caso contrário, o python detectará EOF e sairá.

Então:

python -i < p1

E em outros lugares:

exec 3> p1
echo '1j*1j' >&3
...
# and when done, close that file descriptor so python sees the EOF:
exec 3>&-
    
por 19.04.2013 / 09:27
5

Você pode usar tail -f para manter o fifo aberto após echo escrever nele.

tail -n1 -f p1 | python

Por que isso funciona

python está lendo p1 . Quando chega ao final do arquivo, ele pára de ler. Esse é o comportamento normal das leituras de arquivos, mesmo se o arquivo for um pipe nomeado. tail com o sinalizador -f (follow) continuará lendo de um arquivo após o seu término ser alcançado.

    
por 19.04.2013 / 05:15
2

Você precisa enviar o programa inteiro de uma só vez.

Quando você chamar run python < p1 , o shell está aguardando entrada antes de invocar o python. Isto é, o python nem sequer começa a executar em tudo até que todo o fluxo de dados tenha sido lido pelo shell e então seja passado inteiramente para python .

Mesmo executando python -u p1 (ou seja, sem buffer e lido do arquivo p1 ) python tentará ler o arquivo inteiro antes de executar qualquer um deles.

Experimente esta experiência.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

cat > p1
print "Hello World"
print "Hello World"

Você verá que pode enviar várias linhas, mas o python no Termo 1 não faz nada. Agora pressione ctrl + D . Todo o programa é executado de uma vez.

Então, para resumir, se você quiser que python leia de um pipe, você precisa enviar o programa inteiro. Você não pode usar python interativamente dessa maneira.

    
por 19.04.2013 / 05:26
1

Talvez a abordagem da cauda seja melhor (mais flexível), mas como uma alternativa:

{ echo -n "print \"Hello World\""; cat; } > p1
    
por 19.04.2013 / 05:17