Избегайте разрыва канала с подпроцессом. Откройте и несколько различных запросов

Я работаю над многопоточным скриптом Python, в котором у меня есть специальный поток, отвечающий за выполнение некоторых команд оболочки без повторного открытия новой оболочки zsh, но поддержание того же сеанса живым.

Основной поток помещает команды, подлежащие выполнению, в очередь, которая используется совместно с потоком, отвечающим за выполнение команд.

import threading, Queue
class ShellThread(threading.Thread):
    def __init__(self, command_q, command_e):
        super(ShellThread, self).__init__()
        self.command_q = command_q
        self.command_e = command_e
        self.stoprequest = threading.Event()

        from subprocess import Popen, PIPE
        import os
        self.zsh = Popen("zsh", stdin=PIPE, stdout=PIPE)

    def run(self):
        while not self.stoprequest.isSet():
            try:
                command = self.command_q.get(True, 0.1)
                print "ShellThread is now executing command : " + command
                self.zsh.stdin.write(command + '\n')
                self.zsh.stdin.flush()
                self.command_e.set()

            except Queue.Empty:
                continue

    def join(self, timeout=None):
        self.stoprequest.set()
        self.zsh.stdin.close()
        super(ShellThread, self).join(timeout)

def main(args):
    __command_q = Queue.Queue()
    __command_e = threading.Event()
    __thread = ShellThread(command_q=__command_q, command_e=__command_e)
    __thread.start()

    while 1:
        line = raw_input()
        print 'MainThread : ' + line
        __command_q.put(line)
        __command_e.wait(0.5)
        __command_e.clear()

if __name__ == '__main__':
    import sys
    main(sys.argv[1:])

Это работает, но у меня есть случайный IOError: [Errno 32] Broken pipe ошибки, и я до сих пор не нашел способ получить stdout после выполнения каждой команды.

ОБНОВЛЕНИЕ: Обратите внимание, что весь смысл в том, чтобы держать открытую одну-единственную оболочку zsh (вот почему у меня есть специальный поток для этой цели), чтобы запускать различные команды во времени. Я не могу использовать Popen.communicate так как он закроет оболочку, когда команда будет завершена, и я не знаю всех команд, которые мне придется запускать заранее.

1 ответ

Ошибка в "Сломанной трубе" может быть связана с тем, что вы не используете лучшие функции подпроцесса для выполнения того, что вы хотите сделать.

читать подпроцесс док. Там вы найдете то, что ищете.

ОБНОВИТЬ:

Хорошо отвечая на ваше обновление я выложу мое. Есть как минимум одна вещь, которую вы можете сделать, чтобы увидеть результат. Вы можете перенаправить вывод вашего Popen в sys.stdout, добавить

import sys

в свой код и измените:

self.zsh = Popen("zsh", stdin=PIPE, stdout=PIPE)

от:

self.zsh = Popen("zsh", stdin=PIPE, stdout=sys.stdout)

с этим вы сможете увидеть вывод команд.

Другие вопросы по тегам