python subprocess在正在运行的子进程内插入命令

时间:2015-04-22 20:57:32

标签: python subprocess

我正在运行子进程:

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

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

1 个答案:

答案 0 :(得分:3)

我认为你要问的是如何将命令传递给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关闭PyPI,后者将较新版本的库向后移植到旧版本的Python。
  • 看看current source如何处理input参数并自己做同样的事情。
  • Popen.communicateinput之前收到check_output参数,因此,您只需手动创建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,而不是自己动手。