我有一个与用户交互的程序(像shell一样),我想使用Python子进程模块交互地运行它。这意味着,我希望有可能写入标准输入并立即从标准输出获得输出。我尝试了这里提供的许多解决方案,但似乎没有一个能满足我的需求。
我写的代码基于 Running an interactive command from within Python。
import Queue
import threading
import subprocess
def enqueue_output(out, queue):
for line in iter(out.readline, b''):
queue.put(line)
out.close()
def getOutput(outQueue):
outStr = ''
try:
while True: # Adds output from the queue until it is empty
outStr += outQueue.get_nowait()
except Queue.Empty:
return outStr
p = subprocess.Popen("./a.out", stdin=subprocess.PIPE, stout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize = 1)
#p = subprocess.Popen("./a.out", stdin=subprocess.PIPE, stout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, universal_newlines=True)
outQueue = Queue()
errQueue = Queue()
outThread = Thread(target=enqueue_output, args=(p.stdout, outQueue))
errThread = Thread(target=enqueue_output, args=(p.stderr, errQueue))
outThread.daemon = True
errThread.daemon = True
outThread.start()
errThread.start()
p.stdin.write("1\n")
p.stdin.flush()
errors = getOutput(errQueue)
output = getOutput(outQueue)
p.stdin.write("5\n")
p.stdin.flush()
erros = getOutput(errQueue)
output = getOutput(outQueue)
字符串
问题是队列仍然是空的,就好像没有输出一样。只有当我把程序需要执行和终止的所有输入都写入标准输入时,我才能得到输出(这不是我想要的)。例如,如果我做了这样的事情:
p.stdin.write("1\n5\n")
errors = getOutput(errQueue)
output = getOutput(outQueue)
型
有办法做我想做的事吗?
该脚本将在Linux机器上运行。我修改了我的脚本,删除了universal_newlines=True +将bufsize设置为1,并在写入后立即刷新标准输入。仍然没有得到任何输出。
第二次尝试:
我尝试了这个方法,它对我很有效:
from subprocess import Popen, PIPE
fw = open("tmpout", "wb")
fr = open("tmpout", "r")
p = Popen("./a.out", stdin = PIPE, stdout = fw, stderr = fw, bufsize = 1)
p.stdin.write("1\n")
out = fr.read()
p.stdin.write("5\n")
out = fr.read()
fw.close()
fr.close()
型
4条答案
按热度按时间rt4zxlrg1#
目前的答案对我来说都不起作用。最后,我得到了这个工作:
字符串
使用此
dummy.py
脚本进行测试:型
注意事项是(所有这些都在功能中管理):
readline()
。在我看来,这是一个非常简单的解决方案(不是我的,我在这里找到的:https://eli.thegreenplace.net/2017/interacting-with-a-long-running-child-process-in-python/)。
qc6wkl3g2#
在Linux上有两种解决方案:
第一个是使用一个文件来同时写入输出和从中读取:
字符串
第二,正如J.F.塞巴斯蒂安所提供的,使用fnctl模块使p.stdout和p.stderr管道不阻塞:
型
jxct1oxe3#
这是一个交互式shell。你必须在单独的线程上运行read(),否则它会阻塞write()。
字符串
zxlwwiss4#
据我所知,最简单的方法是在两端创建专用线程:两个用于父进程上的stdout/stderr,一个用于子进程上的stdin。