Mendapatkan stdin dari pipa bernama


10

Apa yang saya coba lakukan adalah menjalankan python di jendela terminal dan mengarahkan stdin dari pipa bernama. Lalu saya menulis ke pipa bernama di terminal lain dan meminta perintah itu mengeksekusi pada python.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

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

Yang terjadi adalah - cetakan Hello Worlddan keluar python . Yang ingin saya lakukan adalah tetap menjalankan python untuk mengambil perintah berikutnya. Bagaimana saya melakukan ini di shell?

Jawaban:


10

Kamu butuh

  • Jalankan python secara interaktif meskipun stdinnya bukan terminal: use python -i
  • biarkan ujung pipa tulisan tetap terbuka, jika tidak python akan mendeteksi EOF dan keluar.

Begitu:

python -i < p1

Dan di tempat lain:

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

Terima kasih! Itu berhasil. Saya tidak terbiasa dengan apa yang telah Anda lakukan. Tolong tambahkan beberapa detail pada jawaban Anda untuk menjelaskan apa yang sedang terjadi. Apa yang sedang exec 3> p1dilakukan dan apa itu &3& exec 3> &1? Terima kasih.
Tuan Loh.

1
Jawaban Anda mengingatkan saya pada spanduk ini - sphotos-b.xx.fbcdn.net/hphotos-ash4/… itu adalah foto sampul seorang teman di facebook :-)
Lord Loh.

Sebuah pertanyaan, apakah akan exec 3>&-berfungsi sama seperti di exec 3>&1sini?
Wildcard

1
@Wildcard Saya kira saya bermaksud menulis di 3>&-sini. 3>&1akan bekerja dengan baik tetapi tidak masuk akal. Terima kasih
Stéphane Chazelas

5

Anda dapat menggunakannya tail -funtuk menjaga fifo tetap terbuka setelah echomenulisnya.

tail -n1 -f p1 | python

Kenapa ini bekerja?

pythonsedang membaca dari p1. Ketika mencapai akhir file, itu berhenti membaca. Ini adalah perilaku normal untuk membaca file, bahkan jika file tersebut adalah pipa bernama. taildengan -fbendera (ikuti) akan terus membaca dari file setelah akhirnya tercapai.


Saya mencoba echo "print \"Hello World\" " > p1di terminal kedua dan tidak ada yang terjadi - tetapi terminal juga tidak diblokir. Terminal dengan python tetap diblokir sampai saya ^cdan keluar dan mengakhiri python dengan pesan interupsi keyboard yang ditampilkan oleh python.
Tuan Loh.

Saya menggunakan tail -ftrik ini ketika membongkar arsip tar blok-split melalui pipa bernama. Itu bekerja dengan sangat baik.
Mael

2

Anda harus mengirim seluruh program sekaligus.

Ketika Anda menelepon jalankan python < p1shell sedang menunggu input sebelum memanggil python. Artinya, python bahkan tidak mulai menjalankan sama sekali sampai seluruh aliran data telah dibaca oleh shell dan kemudian diteruskan secara keseluruhan ke python.

Bahkan menjalankan python -u p1sebaliknya (yaitu, unbuffered dan membaca dari file p1) pythonakan mencoba membaca seluruh file sebelum mengeksekusi semua itu.

Coba percobaan ini.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

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

Anda akan melihat bahwa Anda dapat mengirim banyak baris tetapi python dalam Term 1 tidak melakukan apa-apa. Sekarang tekan ctrl+ D. Seluruh program dijalankan sekaligus.

Jadi, untuk meringkas, jika Anda ingin python membaca dari sebuah pipa, Anda harus mengirim seluruh program. Anda tidak dapat menggunakan python secara interaktif dengan cara ini.


1

Mungkin pendekatan ekor lebih baik (lebih fleksibel) tetapi sebagai alternatif:

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

Ini tidak berfungsi seperti yang saya inginkan. -nmungkin telah dihapus. Dan setelah itu, 0. terminal dengan echoperintah akan diblokir 1. python tidak mengeksekusi perintah sampai aku menekan ^cdi echoterminal dan kedua proses mengakhiri.
Tuan Loh.

1
@ LordLoh. Mungkin menjadi masalah buffering. Mungkin python akan menjalankan perintah jika output yang cukup telah dibuat sehingga baris pertama akhirnya ditulis ke FIFO. Tetapi karena ada solusi yang berhasil, tidak masuk akal untuk berupaya menyelesaikan masalah ini.
Hauke ​​Laging
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.