Pobieranie stdin z nazwanej rury

10

To, co próbuję zrobić, to uruchomić python w oknie terminala i przekierować go stdin z nazwanego potoku. Następnie piszę do nazwanego potoku w innym terminalu i uruchamiam to polecenie w Pythonie.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

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

Co się dzieje - python drukuje Hello Worldi wychodzi. Chcę, aby Python działał, aby wykonać następne polecenie. Jak to zrobić w powłoce?

Lord Loh.
źródło

Odpowiedzi:

10

Musisz

  • Uruchamiaj python interaktywnie, nawet jeśli jego standardowe wejście nie jest terminalem: użyj python -i
  • utrzymuj otwarty koniec zapisu potoku, w przeciwnym razie Python wykryje EOF i zakończy działanie.

Więc:

python -i < p1

I gdziekolwiek:

exec 3> p1
echo '1j*1j' >&3
...
# and when done, close that file descriptor so python sees the EOF:
exec 3>&-
Stéphane Chazelas
źródło
Dzięki! Zadziałało. Nie wiem, co zrobiłeś. Czy możesz dodać kilka szczegółów do swojej odpowiedzi, aby wyjaśnić, co się dzieje. Co exec 3> p1robi i co jest &3& exec 3> &1? Dziękuję Ci.
Lord Loh.
1
Twoja odpowiedź przypomniała mi ten baner - sphotos-b.xx.fbcdn.net/hphotos-ash4/… to zdjęcie z okładki znajomego na Facebooku :-)
Lord Loh.
Pytanie, czy exec 3>&-działałoby tak samo jak exec 3>&1tutaj?
Wildcard
1
@Wildcard Podejrzewam, że zamierzałem 3>&-tutaj pisać . 3>&1działałby również, ale nie miałby sensu. Dzięki
Stéphane Chazelas,
5

Możesz użyć, tail -faby utrzymać fifo otwarte po echozapisaniu do niego.

tail -n1 -f p1 | python

Dlaczego to działa

pythonczyta z p1. Gdy osiągnie koniec pliku, przestaje czytać. Jest to normalne zachowanie w przypadku odczytu pliku, nawet jeśli plik jest nazwanym potokiem. tailz -fflagą (Follow) będzie kontynuować czytanie z pliku po osiągnięciu jego końca.


źródło
Próbowałem echo "print \"Hello World\" " > p1na drugim terminalu i nic się nie stało - ale terminal również nie został zablokowany. Terminal z pythonem pozostawał zablokowany, dopóki ^cgo nie zamknąłem i nie wychodziłem z niego oraz kończę python, wyświetlając komunikat przerwania klawiatury.
Lord Loh.
Użyłem tej tail -fsztuczki podczas rozpakowywania archiwum tar z podziałem bloków przez nazwaną potok. Działa cudownie.
Mael
2

Musisz wysłać cały program na raz.

Po wywołaniu polecenia run python < p1powłoka czeka na dane wejściowe przed wywołaniem Pythona. Oznacza to, że pyton nie rozpocząć wykonywanie wcale aż cały strumień danych został odczytany przez powłokę, a następnie są przekazywane w całości do python.

Nawet uruchomienie python -u p1zamiast tego (tzn. Niebuforowanego i odczytanie z pliku p1) pythonspróbuje odczytać cały plik przed wykonaniem dowolnego z nich.

Wypróbuj ten eksperyment.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

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

Zobaczysz, że możesz wysłać wiele linii, ale python w Term 1 nic nie robi. Teraz naciśnij ctrl+ D. Cały program wykonuje się jednocześnie.

Podsumowując, jeśli chcesz, aby Python czytał z potoku, musisz wysłać cały program. W ten sposób nie można używać Pythona interaktywnie.

bahamat
źródło
1

Być może podejście ogona jest lepsze (bardziej elastyczne), ale alternatywnie:

{ echo -n "print \"Hello World\""; cat; } > p1
Hauke ​​Laging
źródło
To nie działa tak jak chcę. -nmógł zostać usunięty. A potem, 0. Terminal z echopoleceniem zostanie zablokowany 1. pyton nie wykonuje polecenia do pędzę ^cw echoterminalu i zarówno proces zakończyć.
Lord Loh.
1
@LordLoh. Może to być problem z buforowaniem. Prawdopodobnie python wykona polecenie, jeśli utworzono wystarczającą ilość danych wyjściowych, aby pierwszy wiersz został ostatecznie zapisany w FIFO. Ale ponieważ istnieje skuteczne rozwiązanie, nie byłoby sensu wkładać wysiłku w rozwiązanie tego problemu.
Hauke ​​Laging 19.04.13