【发布时间】:2019-12-05 03:06:42
【问题描述】:
我正在使用一款名为 Chimera 的科学软件。本题下游的部分代码,要求我使用Python 2.7。
我想调用一个进程,给那个进程一些输入,读取它的输出,基于它给它更多的输入,等等。
我使用Popen 打开进程,使用process.stdin.write 传递标准输入,但是当进程仍在运行时,我一直在尝试获取输出。 process.communicate() 停止进程,process.stdout.readline() 似乎让我陷入无限循环。
这是我想做的一个简化示例:
假设我有一个名为 exampleInput.sh 的 bash 脚本。
#!/bin/bash
# exampleInput.sh
# Read a number from the input
read -p 'Enter a number: ' num
# Multiply the number by 5
ans1=$( expr $num \* 5 )
# Give the user the multiplied number
echo $ans1
# Ask the user whether they want to keep going
read -p 'Based on the previous output, would you like to continue? ' doContinue
if [ $doContinue == "yes" ]
then
echo "Okay, moving on..."
# [...] more code here [...]
else
exit 0
fi
通过命令行与之交互,我会运行脚本,输入“5”,然后,如果它返回“25”,我会输入“yes”,如果不是,我会输入“no ”。
我想运行一个 python 脚本,我在其中传递 exampleInput.sh "5",如果它返回 "25",那么我传递 "yes"
到目前为止,这是我能得到的最接近的:
#!/home/user/miniconda3/bin/python2
# talk_with_example_input.py
import subprocess
process = subprocess.Popen(["./exampleInput.sh"],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE)
process.stdin.write("5")
answer = process.communicate()[0]
if answer == "25":
process.stdin.write("yes")
## I'd like to print the STDOUT here, but the process is already terminated
但这当然失败了,因为在 `process.communicate()' 之后,我的进程不再运行了。
(以防万一/仅供参考):实际问题
Chimera 通常是一个基于 gui 的应用程序,用于检查蛋白质结构。如果您运行chimera --nogui,它将打开一个提示并接受输入。
在运行下一个命令之前,我经常需要知道 chimera 的输出。例如,我经常会尝试生成蛋白质表面,如果 Chimera 无法生成表面,它不会破裂——它只是通过 STDOUT 这么说的。因此,在我的 python 脚本中,当我循环分析许多蛋白质时,我需要检查 STDOUT 以了解是否继续对该蛋白质进行分析。
在其他用例中,我会先通过 Chimera 运行大量命令来清理蛋白质,然后我会想运行大量单独的命令来获取不同的数据,并使用这些数据来决定是否运行其他命令。我可以获取数据,关闭子进程,然后运行另一个进程,但这需要每次都重新运行所有这些清理命令。
无论如何,这些都是我希望能够将 STDIN 推送到子进程、读取 STDOUT 并且仍然能够推送更多 STDIN 的一些实际原因。
感谢您的宝贵时间!
【问题讨论】:
-
查看this article(特别是“与孩子的标准输入和标准输出直接交互”部分)。看起来您需要对标准输入和标准输出进行一系列
.close()和.flush()调用。 -
没有什么期待?
-
这正是pexpect 的用途。我强烈建议尝试直接使用 subprocess 进行处理,因为 pexpect 会抽象出大部分流处理细节。
标签: python subprocess scientific-software