12

我正在尝试在 Python 中使用子进程来保持外部脚本以类似服务器的方式打开。外部脚本首先加载一个模型。完成后,它会通过 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 - out 将只是空的,无论我使用stdout.read()or stdout.readline()。但是,当我tokenizer.stdin.close()在读取 STDOUT 之前关闭标准输入时它会起作用,但这会关闭子进程,这不是我想要的,因为我必须在发送另一个请求之前再次重新加载整个外部脚本。

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

4

2 回答 2

6

多亏了这个 Answer,我发现必须使用从句柄才能与子进程正确通信:

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
于 2012-11-28T13:09:37.463 回答
2

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

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

否则,有时可以通过将程序附加到伪 TTY 来使程序不缓冲其输出(包括 stdlib 在内的许多程序都假设当它们的输出进入 TTY 时,不需要缓冲)。但这有点棘手。

于 2012-11-28T12:54:32.487 回答