如何写入Python子进程';史坦?

如何写入Python子进程';史坦?,python,subprocess,stdin,nuke,Python,Subprocess,Stdin,Nuke,我正在尝试编写一个Python脚本来启动一个子进程,并写入子进程stdin。我还希望能够确定在子流程崩溃时要采取的操作 我尝试启动的过程是一个名为nuke的程序,它有自己的内置Python版本,我希望能够向其提交命令,然后在命令执行后告诉它退出。到目前为止,我已经计算出,如果我在命令提示符下启动Python,然后作为子进程启动nuke,那么我可以在nuke中键入命令,但是我希望能够将这一切都放在一个脚本中,这样Python主程序就可以启动nuke,然后写入它的脚本(并因此进入其内置版本的Pyth

我正在尝试编写一个Python脚本来启动一个子进程,并写入子进程stdin。我还希望能够确定在子流程崩溃时要采取的操作

我尝试启动的过程是一个名为
nuke
的程序,它有自己的内置Python版本,我希望能够向其提交命令,然后在命令执行后告诉它退出。到目前为止,我已经计算出,如果我在命令提示符下启动Python,然后作为子进程启动
nuke
,那么我可以在
nuke
中键入命令,但是我希望能够将这一切都放在一个脚本中,这样Python主程序就可以启动
nuke
,然后写入它的脚本(并因此进入其内置版本的Python)并告诉它做一些时髦的事情,因此我编写了一个脚本,以如下方式启动
nuke

subprocess.call(["C:/Program Files/Nuke6.3v5/Nuke6.3", "-t", "E:/NukeTest/test.nk"])
然后什么也没有发生,因为nuke正在等待用户输入。我现在如何写入标准输入


我这样做是因为我运行了一个带有
nuke
的插件,该插件在渲染多个帧时会导致它间歇性崩溃。所以我希望这个脚本能够启动
nuke
,告诉它做些什么,然后如果它崩溃了,再试一次。因此,如果有办法捕获崩溃并仍然正常,那就太好了。

可以为
subprocess.call()
stdin
参数提供类似文件的对象

Popen
对象的

要捕获输出,您应该改为使用
子流程。检查\u output()
,它采用类似的参数。从文档中可以看出:

>>> subprocess.check_output(
...     "ls non_existent_file; exit 0",
...     stderr=subprocess.STDOUT,
...     shell=True)
'ls: non_existent_file: No such file or directory\n'
最好使用:

“更好”,由于此警告:

使用communicate()而不是.stdin.write、.stdout.read或.stderr.read,以避免由于任何其他操作系统管道缓冲区填满并阻塞子进程而导致死锁


为了澄清一些问题:

如前所述,正确的方法是使用
子流程。通信

但是,当使用
subprocess.communication
input
传送
stdin
时,需要根据

请注意,如果要将数据发送到进程的stdin,则需要使用stdin=PIPE创建Popen对象。类似地,要在结果元组中获取除无以外的任何内容,还需要指定stdout=PIPE和/或stderr=PIPE

在评论中还提到,对于Python 3.4,您需要对字符串进行编码,这意味着您需要将字节传递给
输入
,而不是
字符串
。这并不完全正确。根据文档,如果流是以文本模式打开的,则输入应该是字符串(源是同一页面)

如果流是以文本模式打开的,则输入必须是字符串。否则,输入必须是字节

因此,如果流没有在文本模式下显式打开,那么下面的内容应该可以工作:

导入子流程
command=['myapp','--arg1','value\u for\u arg1']
p=subprocess.Popen(命令,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.stdout)
output=p.communicate(input='some data'.encode())[0]
我特意将上面的
stderr
值作为
STDOUT
作为示例

也就是说,有时您可能希望获得另一个进程的输出,而不是从头开始构建它。假设您希望运行与echo-n'CATCH\nme'| grep-i CATCH | wc-m等效的
echo-n'CATCH\nme'| grep-i CATCH | wc-m。这通常应返回'CATCH'中的数字字符加上换行字符,结果是6re是将
CATCH\nme
数据馈送给grep。因此,我们可以使用Python子进程链中的stdin作为变量将数据馈送给grep,然后将stdout作为管道传递给
wc
进程的stdin(同时,去掉额外的换行符):

导入子流程
要捕获的内容='catch'
喂什么='CATCH\n我'
#我们创建第一个子流程,注意我们需要stdin=PIPE和stdout=PIPE
p1=subprocess.Popen(['grep','-i',what_to_catch],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
#我们立即运行第一个子流程并得到结果
#请注意,我们对数据进行了编码,否则会出现类型错误
p1_out=p1.communication(输入=what_to_feed.encode())[0]
#结果在末尾包含一个“\n”,
#如果我们想用一种非常粗糙的方式摆脱它
p1_out=p1_out.decode().strip().encode()
#我们创建第二个子流程,注意我们需要stdin=PIPE
p2=subprocess.Popen(['wc','-m'],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
#我们运行第二个子流程,将第一个子流程的输出提供给它。
#我们对输出进行解码以转换为字符串
#我们还有一个“\n”,所以我们去掉了它
输出=p2。通信(输入=p1_out)[0]。解码().strip()
这与响应有些不同,在响应中,直接通过管道传输两个进程,而不直接在Python中添加数据


希望这能帮助一些人。

aah太好了,谢谢你,如果我只是做了一个导入子流程,我还需要导入popen管道吗?不,你不需要,但是你需要引用它们,比如
subprocess.PIPE
。这个方法还导入子流程模块中的所有内容。
from subprocess import PIPE
引入进入当前名称空间,以便只使用
管道
通信
方法读取数据,直到收到EOF。如果要动态与流程交互,请使用
p.stdin.write('data')访问管道
。关于阅读内容,请参阅我之前的评论。警告是关于这种通信方式的,所以请注意不要填满缓冲区。验证这一点的最简单方法是尝试一下……对于python 3.4,您需要执行
p.communicate(input=“data For input”.encode())
Wh
from subprocess import Popen, PIPE, STDOUT
p = Popen(['myapp'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
stdout_data = p.communicate(input='data_to_write')[0]