#python #subprocess #pipe #stdin
#питон #подпроцесс #труба #стандартный код #python #канал #стандартный интерфейс
Вопрос:
У меня есть метод, который создает подпроцесс и подключает его STDIN к анонимному каналу; который не работает. Он не вызывает никаких исключений, подпроцесс, похоже, просто никогда не считывает данные. (подпроцесс — это исполняемый файл ‘zenity’ для отображения индикатора выполнения в графическом интерфейсе)
class Screen(object):
def __init__(self, display = ":0", bin = '/usr/bin/zenity'):
self.bin = bin
os.environ['DISPLAY'] = display
self.dis = display
def displayProgress(self, text, pulse = True, title = 'Progess'):
'''Method to represent the 'zenity --progress' command
'''
readp, writep = os.pipe()
reade, writee = os.pipe()
rfd = os.fdopen(readp, 'r')
wfd = os.fdopen(writep, 'w')
if pulse:
zenhandle = Popen([self.bin, '--progress',
'--title=%s' % title,
'--auto-close',
'--pulsate'],
stdin = rfd)
else:
zenhandle = Popen([self.bin, '--progress',
'--title=%s' % title,
'--auto-close'],
stdin = rfd)
self.progress = wfd
Идея заключается в том, что вызов метода будет неблокирующим, и я могу write()
Screen.progress
и должен записать его в STDIN дочернего процесса (zenity). (zenity рисует гистограмму завершения, считывая значения из STDIN)
Поле рисуется на экране, но Screen.progress.write('50')
никогда не обновляет панель.
Что я делаю не так?
Редактировать:
При интерактивном запуске, как только я выхожу из оболочки python, панель начинает двигаться. (пульсирующий) Это означает, что он читает -что-то — только после завершения процесса python.
Комментарии:
1. вам действительно нужно вручную создавать свой собственный канал? Почему бы не попросить подпроцесс обработать это за вас. например
handle = subprocess.Popen('cat', stdin=subprocess.PIPE); handle.stdin.write('hello')
2. Это сработает, исходя из примеров кода, которые я просмотрел для подпроцесса, я думал, что stdin был прочитан из аргументов в метод communicate (). Спасибо!
Ответ №1:
os.fdopen()
размер буфера должен быть равен 0. Используйте rfd = os.fdopen(readp, 'r', 0)
.
Ответ №2:
Вероятно, вам нужно очистить файловые буферы. Попробуйте выполнять self.progress.flush()
после каждой записи.
Комментарии:
1. Это было оно! так просто. Я изменил
fdopen()
, чтобы использовать bufsize равный 0, и это работает без промывки. Спасибо!