Отримання stdin з названої труби


10

Що я намагаюся зробити, це запустити python у вікно терміналу і перенаправити його stdin з названої труби. Потім я записую в названу трубу в інший термінал і маю цю команду виконувати на python.

Термінал 1:

mkfifo p1
python < p1

Термінал 2:

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

Що відбувається, це - друкує Hello Worldта виходить пітон . Що я хочу зробити, це тримати python для отримання наступної команди. Як це зробити в оболонці?

Відповіді:


10

Тобі потрібно

  • Запускайте python інтерактивно, навіть якщо його stdin не є терміналом: use python -i
  • тримайте пишучий кінець труби відкритим, інакше пітон виявить EOF та вийде.

Тому:

python -i < p1

І в інших місцях:

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

Дякую! Це спрацювало. Я не знайомий з тим, що ти зробив. Скажіть, будь ласка, якісь деталі у своїй відповіді, щоб пояснити, що відбувається. Що exec 3> p1робить і що &3& exec 3> &1? Дякую.
Лорд Лох.

1
Ваша відповідь нагадала мені цей банер - sphoto-b.xx.fbcdn.net/hphotos-ash4/… це фотографії обкладинки друга у фейсбуці :-)
лорд Лох.

Питання, чи exec 3>&-працюватиме так само, як exec 3>&1тут?
Wildcard

1
@Wildcard Я підозрюю, що мав намір писати 3>&-тут. 3>&1буде добре працювати, але мало сенсу. Спасибі
Стефан Шазелас

5

Ви можете використовувати tail -fдля того, щоб відкрити фіфо після відкриття echoзапису.

tail -n1 -f p1 | python

Чому це працює

pythonчитає з p1. Коли він доходить до кінця файлу, він перестає читати. Це нормальна поведінка для зчитування файлів, навіть якщо файл називається трубою. tailз -fпрапорцем (слідувати) буде читати з файлу після досягнення його кінця.


Я спробував echo "print \"Hello World\" " > p1у другому терміналі, і нічого не сталося - але термінал теж не був заблокований. Термінал з python залишається заблокованим, поки я ^cне вийду з нього та закінчую python, коли python відображається повідомлення про переривання клавіатури.
Лорд Лох.

Цей tail -fтрюк я використав, коли розпаковував блок-розділений архів дьогтю через названу трубку. Це чудово працювало.
Майл

2

Потрібно відправити всю програму відразу.

Під час виклику запуску python < p1оболонка чекає на вхід до виклику python. Тобто, пітон НЕ навіть почати виконання на всіх , поки весь потік даних не прочитано оболонкою , а потім передається в повному обсязі в python.

Навіть працюючий python -u p1натомість (тобто розблокований та зчитуваний з файлу p1) pythonспробує прочитати весь файл перед тим, як виконати будь-який із них.

Спробуйте цей експеримент.

Термінал 1:

mkfifo p1
python < p1

Термінал 2:

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

Ви побачите, що ви можете надсилати кілька рядків, але python у Term 1 нічого не робить. Тепер натисніть ctrl+ D. Вся програма виконується відразу.

Отже, підсумовуючи, якщо ви хочете, щоб пітон читав з труби, вам потрібно надіслати всю програму. Ви не можете використовувати python інтерактивно таким чином.


1

Можливо, підхід до хвоста є кращим (більш гнучким), але в якості альтернативи:

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

Це працює не так, як я хочу. -nможливо, буде видалено І після цього, 0. Термінал з echoкомандою блокується 1. python не виконує команду, поки я не натискаю ^cв echoтерміналі і обидва процеси завершуються.
Лорд Лох.

1
@LordLoh. Може бути проблемою буферизації. Ймовірно, python виконає команду, якщо буде створено достатню кількість результатів, щоб перший рядок, нарешті, був записаний у FIFO. Але оскільки існує робоче рішення, не було б сенсу докладати зусиль для вирішення цієї проблеми.
Hauke ​​Laging
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.