LINUX.ORG.RU

Интерактивное взаимодействие с подпроцессом из Python

 ,


1

1

Допустим, есть задача — из программы на Python интерактивно взаимодействовать с другой программой через стандартный ввод-вывод. Не один раз ввести данные и одни раз считать вывод, а писать-читать-писать-читать…

Вообще для запуска другой программы используется модуль subprocess (есть альтернативы, но они объявлены устаревшими).

Вот пример кода:

import subprocess
bconsole = subprocess.Popen(['bacula-console'], shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
bconsole.stdin.write('messages\n')
bconsole.stdout.read()

Однако при этом на последней функции программа зависает.

Есть метод communicate(). С данным кодом работает, но после его выполнения процесс завершается, что меня не устраивает, т.к. после считывания нужно вводить новые данные.

Собственно, как быть?

☆☆☆☆☆

Ответ на: комментарий от true_admin

Пишет, что нет такого атрибута. Python версии 2.7.

Хотя readline действительно читает, но, как строки кончаются, виснет.

Ttt ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Ttt

Не силён в python2, могу посоветовать поискать советы в гугле типа этого: http://stackoverflow.com/questions/8980050/persistent-python-subprocess Или же select натравить на stdout и смотреть когда данные придут.

Кстати, а bacula python bindings не дают нужного функционала?

true_admin ★★★★★
()

После окончания записи в stdin надо вызывать stdin.flush() В подпроцессе тоже stdout должен сбрасывать буфера.

С завершением работы - при попытке чтения из закрытого пайпа должен отваливаться по EOF, там проблем быть не должно.

AIv ★★★★★
()
Ответ на: комментарий от true_admin

Кстати, а bacula python bindings не дают нужного функционала?

Если бы я их нашёл :) Ты про эти? Если это полная документация, то нужное не находится. Задача заключается в том, чтобы перезагрузить конфигурационные файлы (команда reload) и, если в конфиге ошибка, выявить, в каком она файле (в messages эта информация есть).

Ttt ☆☆☆☆☆
() автор топика
Ответ на: комментарий от AIv

Если выполнить bconsole.stdin.flush() и bconsole.stdout.flush(), то после них при чтении тоже виснет.

Ttt ☆☆☆☆☆
() автор топика
Ответ на: комментарий от true_admin

Не силён в python2, могу посоветовать поискать советы в гугле типа этого: http://stackoverflow.com/questions/8980050/persistent-python-subprocess Или же select натравить на stdout и смотреть когда данные придут.

А вот это (с fcntl) вроде сработало, спасибо.

Ttt ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Ttt

stdout.flush() должно выполняться на стороне подпроцесса а не на стороне родителя. Виснет потому, что либо нету данных, либо данные не оспровождаются концом строки (если испольщуется readline).

А вообще надо знать сколько надо прочитать, либо в байтах, либо в строках.

AIv ★★★★★
()
Последнее исправление: AIv (всего исправлений: 1)
Ответ на: комментарий от AIv

После окончания записи в stdin надо вызывать stdin.flush()

Там же перевод строки, как, наверняка, и в выводе от бакулы. Я проверял, у меня без flush работало.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Перевод строки flush не вызывает. print м.б. вызывает, ХЗ - еще от версии питона м.б. зависит. А вот просто read() читает ЕМНИП «сколько есть», и это вообще то неправильно.

AIv ★★★★★
()
Ответ на: комментарий от AIv

Перевод строки flush не вызывает.

так там же (по дефолту) line buffering, \n вызываешь implicit flush.

А вот просто read() читает ЕМНИП «сколько есть»

Ну, ему можно указать размер «сколько надо». Но это всё равно для текстового io неудобно, поэтому есть readline()

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

так там же (по дефолту) line buffering, \n вызываешь implicit flush.

Первый раз слышу. Это у write? Если да, то это хреново вообще то, я был о них лучшего мнения.

AIv ★★★★★
()
Ответ на: комментарий от AIv

Это, вообще говоря, настраивается. Но в питоне были какие-то эпические грабли с этим (из-за множества обёрток, имхо), поэтому все тупо делают flush() во избежание проблем. Т.е. отключить буферизацию можно, но это в каких-то случаях у меня не работало.

true_admin ★★★★★
()
Ответ на: комментарий от xpahos

Я уже писал, что не нашёл, как дать команду reload.

Ttt ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Siado

Я сижу на трёшке с конца 2009-го когда оно только в svn появилось.

true_admin ★★★★★
()

Да куча есть способов взаимодействия. от простого PIPE и соккетов, до XML-RPC, DBus и XMPP.

AGUtilities ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.