Ottenere stdin da una pipa denominata


10

Quello che sto cercando di fare è eseguire Python in una finestra del terminale e reindirizzare lo stdin da una named pipe. Quindi scrivo sulla pipa denominata in un altro terminale e faccio eseguire quel comando su Python.

Terminale 1:

mkfifo p1
python < p1

Terminale 2:

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

Quello che succede è che Python stampa Hello Worlded esce. Quello che voglio fare è mantenere Python in esecuzione per eseguire un comando successivo. Come posso farlo nella shell?

Risposte:


10

Devi

  • Esegui python in modo interattivo anche se il suo stdin non è un terminale: usa python -i
  • tieni aperta la fine della scrittura della pipe, altrimenti Python rileverà EOF e uscirà.

Così:

python -i < p1

E altrove:

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

Grazie! Ha funzionato. Non ho familiarità con quello che hai fatto. Vorresti aggiungere alcuni dettagli alla tua risposta per spiegare cosa sta succedendo. Cosa sta exec 3> p1facendo e cosa è &3& exec 3> &1? Grazie.
Lord Loh.

1
La tua risposta mi ha ricordato questo banner - sphotos-b.xx.fbcdn.net/hphotos-ash4/… è la foto di copertina di un amico su Facebook :-)
Lord Loh.

Una domanda, exec 3>&-funzionerebbe come exec 3>&1qui?
Carattere jolly

1
@Wildcard Sospetto di voler scrivere 3>&-qui. 3>&1funzionerebbe anche ma avrebbe poco senso. Grazie
Stéphane Chazelas il

5

Puoi usare tail -fper tenere aperto il FIFO dopo averlo echoscritto.

tail -n1 -f p1 | python

Perché questo funziona

pythonsta leggendo da p1. Quando raggiunge la fine del file, termina la lettura. Questo è un comportamento normale per le letture dei file, anche se il file è una pipe denominata. tailcon il -fflag (follow) continuerà a leggere da un file una volta raggiunta la fine.


Ho provato echo "print \"Hello World\" " > p1nel secondo terminale e non è successo nulla, ma neanche il terminale è stato bloccato. Il terminale con Python è rimasto bloccato fino a quando non ^clo ho, lo esce e termina Python con un messaggio di interruzione della tastiera visualizzato da Python.
Lord Loh.

Ho usato questo tail -ftrucco per decomprimere l'archivio tar suddiviso in blocchi attraverso una pipa denominata. Ha funzionato meravigliosamente.
Mael,

2

Devi inviare l'intero programma in una volta.

Quando chiamate run, python < p1la shell è in attesa di input prima di invocare python. Cioè, python non inizia nemmeno a eseguirsi fino a quando l'intero flusso di dati non è stato letto dalla shell e poi è passato per intero a python.

Anche l'esecuzione python -u p1(ovvero, senza buffer e lettura da file p1) pythonproverà a leggere l'intero file prima che venga eseguito.

Prova questo esperimento.

Terminale 1:

mkfifo p1
python < p1

Terminale 2:

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

Vedrai che puoi inviare più righe ma Python nel Term 1 non fa nulla. Ora premi ctrl+ D. L'intero programma viene eseguito contemporaneamente.

Quindi, per riassumere, se vuoi che Python legga da una pipe devi inviare l'intero programma. Non puoi usare Python in modo interattivo in questo modo.


1

Forse l'approccio della coda è migliore (più flessibile) ma in alternativa:

{ echo -n "print \"Hello World\""; cat; } > p1

Questo non funziona come voglio. -npotrebbe essere stato rimosso. Dopodiché, 0. Il terminale con il echocomando viene bloccato 1. python non esegue il comando finché non premo ^cil echoterminale ed entrambi i processi terminano.
Lord Loh.

1
@LordLoh. Potrebbe essere un problema di buffering. Probabilmente python eseguirà il comando se è stato creato un output sufficiente in modo che la prima riga venga finalmente scritta in FIFO. Ma poiché esiste una soluzione funzionante, non avrebbe senso impegnarsi per risolvere questo problema.
Hauke ​​Laging,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.