Взаимодействие с другим запущенным процессом через stdin / stdout
Для имитации случая использования, когда скрипт Python запускает интерактивный процесс командной строки и отправляет / получает текст через stdin / stdout , у нас есть основной скрипт, который запускает другой Python процесс, выполняющий простой интерактивный l oop.
. Это также может быть применено к случаям, когда Python скрипт должен запустить другой процесс и просто прочитать его выводится без каких-либо интерактивных действий.
основной скрипт
import subprocess
import threading
import queue
import time
if __name__ == '__main__':
def enqueue_output(outp, q):
for line in iter(outp.readline, ''):
q.put(line)
outp.close()
q = queue.Queue()
p = subprocess.Popen(["/usr/bin/python", "/test/interact.py"],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
# stderr = subprocess.STDOUT,
bufsize = 1,
encoding ='utf-8')
th = threading.Thread(target=enqueue_output, args=(p.stdout, q))
th.daemon = True
th.start()
for i in range(4):
print("dir()", file=p.stdin)
print(f"Iteration ({i}) Parent received: {q.get()}", end='')
# p.stdin.write("dir()\n")
# while q.empty():
# time.sleep(0)
# print(f"Parent: {q.get_nowait()}")
взаимодействующий скрипт
if __name__ == '__main__':
for i in range(2):
cmd = raw_input()
print("Iteration (%i) cmd=%s" % (i, cmd))
result = eval(cmd)
print("Iteration (%i) result=%s" % (i, str(result)))
output
Iteration (0) Parent received: Iteration (0) cmd=dir()
Iteration (1) Parent received: Iteration (0) result=['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'cmd', 'i']
Iteration (2) Parent received: Iteration (1) cmd=dir()
Iteration (3) Parent received: Iteration (1) result=['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'cmd', 'i', 'result']
Эти вопросы и ответы были использованы для имитации неблокирующих операций чтения из целевого процесса: { ссылка }
This метод обеспечивает способ проверки вывода без блокировки в основном потоке; q.empty()
скажет вам, если нет данных. Вы также можете поиграть с блокировкой вызовов, используя q.get()
или с тайм-аутом q.get(2)
- параметр - количество секунд. Это может быть значение с плавающей запятой меньше нуля.
Текстовое взаимодействие между процессами может выполняться без потока и очереди, но эта реализация дает больше возможностей для получения данных, возвращающихся.
Параметры Popen()
, bufsize=1
и encoding='utf-8'
позволяют использовать <stdout>.readline()
из основного сценария и устанавливают кодировку в ascii-совместимый код c, понимаемый обоими процессами (1 - это не размер буфер, это символьное значение c, указывающее буферизацию строки).
При такой конфигурации оба процесса могут просто использовать print()
для отправки текста друг другу. Эта конфигурация должна быть совместимой со многими интерактивными текстовыми инструментами командной строки.