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?

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>&-

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.


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.


1

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

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.