python 子进程在 运行 子进程中插入命令

python subprocess insert commands inside of a running subprocess

我有一个子进程 运行ning:

cmd="bin/candc --models models"
subprocess.check_output('{} | tee /dev/stderr'.format( cmd ), shell=True,cwd=os.path.abspath('candc'))

我希望能够插入更多只能被当前 运行ning 子进程识别的命令。
请注意,必须有一个 cwd=os.path.abspath('candc') 参数,以便从二进制文件夹外部调用子进程,否则它不会 运行.
C&C 是一个 NLP 库,它实际上要做的是解析给定的句子。我希望能够将一句话传递给子流程。我该怎么做?

我想你问的是如何将命令传递给 candc 的标准输入,就像你 运行 在命令行上输入命令并在其界面上键入命令一样。


如果您可以将所有命令作为一个大字符串一次传递(大概由换行符连接),则可以使用 input 参数来实现,如 check_output 中的示例所示文档:

cmd="bin/candc --models models"
commands="""first candc command
second candc command
third candc command
"""
subprocess.check_output('{} | tee /dev/stderr'.format(cmd), shell=True,
                        cwd=os.path.abspath('candc'),
                        input=commands)

如果这是 Python 3.x,您还必须为 commands 使用编码字节,或者添加 universal_newlines=True 使 check_output 为你。如果您的命令是纯 ASCII,则前者更容易;只需将该行更改为 commands = b"""….

如果这是一个足够旧的版本(我认为这意味着 2.6/3.2,但我不确定——查看上面链接的文档),input 参数还不存在。在这种情况下,您有三个选择:

  • 安装 subprocess32 off PyPI,它将新版本的库反向移植到旧版本的 Python。
  • 看看 current source 如何处理 input 参数,然后自己做完全相同的事情。
  • Popen.communicatecheck_output 之前接受了一个 input 参数,因此,您可以手动创建一个 Popen 并在其上调用 communicate

最后一个基本上只是第二个的简单版本……但它要简单得多。事实上,如果你不需要处理超时和对输出做一些额外的复杂性等等,它只是一个两行代码:

p = subprocess.Popen('{} | tee /dev/stderr'.format(cmd), shell=True,
                     cwd=os.path.abspath('candc'), stdin=PIPE)
p.communicate(commands)

如果您需要以交互方式发送命令(在发送下一个之前等待一个响应),那么 check_output 不能这样做。它只是 Popen 对象的便利包装器。相反,您将想要显式创建一个 Popen 对象,然后执行 p.stdin.writep.stdout.read 与其通信。

例如,一个快速而复杂的版本可能是:

p = subprocess.Popen('{} | tee /dev/stderr'.format(cmd), shell=True,
                     cwd=os.path.abspath('candc'), 
                     stdin=PIPE, stdout=PIPE)
for command in commands.splitlines():
    p.stdout.readline() # read and ignore a prompt
    p.stdin.write(command + '\n')
rc = p.wait()
if rc: raise SomeException() # this is the check in check_output

但是,如果提示超过一行,或者不能保证适合一个缓冲区,或者……

,则该代码可能会阻塞

一般来说,这很难做到正确。 (Python 本身在 communicate 函数中直到 3.2 或 3.3 才正确......)特别是如果你不明白文档在谈论什么阻塞输出管道。因此,如果这确实是您所需要的,您可能需要考虑使用第三方库来驱动交互式命令行程序,例如 pexpect,而不是自己动手。