Переадресация подпроцесса Python stdout не идет в трубу, если она не закрыта? - PullRequest
0 голосов
/ 12 июля 2019

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

import subprocess
command = "smbclient <someIP> -U <username>"
p = subprocess.Popen(command,shell=True, executable='/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.stdin.write(b"ls\n")
p.stdin.flush()
p.stdout.readline() # this blocks
p.stdin.close()
p.stdout.readline() # this works (grabs data as expected), also p.communicate() works as well but that makes sense since it closes stdin

Я не могу понять, почему нет выхода после очистки stdin.У меня было несколько подозрений, которые я тоже проверил:

  1. Я пытался проверить, будет ли работать неблокирующее чтение.Я запустил fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK) и сделал read(), readline() и т. Д. После сброса, и это не сработало.
  2. Попытался сбросить p.stdout до чтения, и это не сработало.
  3. Попытка удалить трубу stdout из конструктора, чтобы она просто переходила к stdout системы.Вот где это становится действительно интересным.Если я делаю это, как только я сбрасываю stdin, я вижу вывод в моем терминале.Я могу продолжать писать и сбрасывать, не воссоздавая процесс, и каждый раз, когда я это делаю, вывод идет на терминал, как и ожидалось, без необходимости закрывать stdin.Так что, почему это не идет к трубе, сбивает с толку.
  4. Пробный конвейер tail -f mycommands.txt | smbclient <myParameters> в подсказке bash, и это работало просто отлично - я проверял, ждал ли он EOF или чего-то такого, чтобына самом деле обрабатывать команды.
  5. Изменено /bin/bash на /bin/sh, чтобы посмотреть, было ли это bash -специфическая вещь, но это не имело никакого значения.

Яработает Python 3.5.2.Что может быть причиной поведения, которое я вижу?Почему чтение только работает после закрытия стандартного ввода, но не перенаправления stdout работает просто отлично?Я просто не могу понять поведение, которое вижу, и не могу воспроизвести с помощью других команд.Я понимаю, что, возможно, я мог бы использовать один из представленных новых асинхронных API, но я действительно хочу понять, что может быть корнем этого поведения.Обратите внимание, что в ответ на ls отправляется очень небольшое количество данных, поэтому оно, конечно, не заполняется до полной емкости.

...