Подключение к stdin подпроцесса к каналу

#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, и это работает без промывки. Спасибо!