Obtendo stdin de um pipe nomeado

10

O que estou tentando fazer é executar o python em uma janela de terminal e redirecionar o stdin de um pipe nomeado. Em seguida, escrevo no 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 é - o python imprime Hello Worlde sai. O que eu quero fazer é manter o python em execução para executar o próximo comando. Como faço isso no shell?

Lorde Loh.
fonte

Respostas:

10

Você precisa

  • Execute o python interativamente, mesmo que o stdin não seja um terminal: use python -i
  • mantenha a extremidade de gravação do pipe aberta, caso contrário, o python detectará o EOF e sairá.

Assim:

python -i < p1

E em outro lugar:

exec 3> p1
echo '1j*1j' >&3
...
# and when done, close that file descriptor so python sees the EOF:
exec 3>&-
Stéphane Chazelas
fonte
Obrigado! Funcionou. Não estou familiarizado com o que você fez. Você poderia adicionar alguns detalhes à sua resposta para explicar o que está acontecendo. O que está exec 3> p1fazendo e o que é &3& exec 3> &1? Obrigado.
Senhor Loh.
1
Sua resposta me lembrou este banner - sphotos-b.xx.fbcdn.net/hphotos-ash4/… é a foto de capa de um amigo no facebook :-)
Lord Loh.
Uma pergunta, exec 3>&-funcionaria da mesma forma que exec 3>&1aqui?
Curinga
1
@Wildcard Eu suspeito que pretendia escrever 3>&-aqui. 3>&1funcionaria tão bem, mas faria pouco sentido. Obrigado
Stéphane Chazelas
5

Você pode usar tail -fpara manter o fifo aberto depois de gravá echo-lo.

tail -n1 -f p1 | python

Por que isso funciona

pythonestá lendo p1. Quando chega ao final do arquivo, para de ler. Esse é um comportamento normal para leituras de arquivos, mesmo se o arquivo for um pipe nomeado. tailcom o -fsinalizador (a seguir) continuará lendo um arquivo após seu término.


fonte
Eu tentei echo "print \"Hello World\" " > p1no segundo terminal e nada aconteceu - mas o terminal também não foi bloqueado. O terminal com python permaneceu bloqueado até eu ^csair, sair e finalizar o python com uma mensagem de interrupção do teclado sendo exibida pelo python.
Senhor Loh.
Eu usei esse tail -ftruque ao descompactar o arquivo tar dividido em blocos por meio de um pipe nomeado. Funcionou maravilhosamente.
Mael
2

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

Quando você chama executar, python < p1o shell está aguardando a entrada antes de chamar o python. Ou seja, python nem sequer começar a executar em tudo até que todo o fluxo de dados foi lido pelo shell e, em seguida, é passado em sua totalidade para python.

Até mesmo a execução python -u p1(ou seja, sem buffer e lida do arquivo p1) pythontentará ler o arquivo inteiro antes que ele seja executado.

Tente este experimento.

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. O programa inteiro é executado de uma só vez.

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

bahamat
fonte
1

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

{ echo -n "print \"Hello World\""; cat; } > p1
Hauke ​​Laging
fonte
Isso não funciona como eu quero. -npode ter sido removido. E depois disso, 0. O terminal com o echocomando é bloqueado 1. python não executa o comando até eu pressionar ^co echoterminal e os dois processos terminarem.
Senhor Loh.
1
@LordLoh. Pode ser um problema de buffer. Provavelmente o python executará o comando se uma saída suficiente tiver sido criada para que a primeira linha finalmente seja gravada no FIFO. Mas, como existe uma solução funcional, não faria sentido esforçar-se para resolver esse problema.
amigos estão dizendo sobre hauke laging