重复写入STDIN并读取子进程的STDOUT而不关闭它

时间:2012-11-28 10:52:46

标签: python

我正在尝试在Python中使用Subprocess来保持外部脚本以类似服务器的方式打开。外部脚本首先加载模型。完成后,它通过STDIN接受请求并将处理后的字符串返回给STDOUT。

到目前为止,我已经尝试了

tokenizer = subprocess.Popen([tokenizer_path, '-l', lang_prefix], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

但是,我无法使用

tokenizer.stdin.write(input_string+'\n')
out = self._tokenizer.stdout.readline()

为了通过子进程重复处理input_strings - 无论是否使用stdout.read()stdout.readline(),out都将为空。但是,当我在读取STDOUT之前用tokenizer.stdin.close()关闭stdin时它会起作用,但这会关闭子进程,这不是我想要的,因为我必须在发送另一个请求之前再次重新加载整个外部脚本。

有没有办法在python中以类似服务器的方式使用子进程而不关闭并重新打开它?

2 个答案:

答案 0 :(得分:2)

感谢this Answer,我发现必须使用slave handle才能正确地与子流程进行通信:

master, slave = pty.openpty()
tokenizer = subprocess.Popen(script, shell=True stdin=subprocess.PIPE, stdout=slave)
stdin_handle = process.stdin
stdout_handle = os.fdopen(master)

现在,我可以通过

与子流程进行通信而不关闭它
stdin_handle.write(input)
stdout_handle.readline() #gets the processed input

答案 1 :(得分:1)

您的外部脚本可能会缓冲其输出,因此只有在刷新子级中的缓冲区(子级必须自己执行)时才能在父级中读取它。使其刷新缓冲区的一种方法可能是关闭输入,因为它以适当的方式终止并在进程中刷新其缓冲区。

如果您可以控制外部程序(即,如果您可以修补它),请在输出后插入一个刷新。

否则程序有时可以通过将它们附加到伪TTY来缓冲它们的输出(许多程序,包括stdlib,假设当它们的输出转到TTY时,不希望缓冲)。但这有点棘手。