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.