Python子进程Popen在处理所有命令之前挂起

时间:2017-06-27 13:53:21

标签: python ipython mpi jupyter-notebook

这是我在Jupyter Notebook %%bash魔法单元中的初始问题/观察,它也在IPython控制台中重现。我打算从笔记本页面启动几个MPI程序。在这里,我使用date系统命令作为简单的再现器。

In [1]: %%bash
   ...: echo "First"
   ...: mpirun -np 2 date
   ...: echo "Second"
   ...: mpirun -np 2 date
   ...: echo "End"
   ...: 
First
mar. juin 27 15:17:36 CEST 2017
mar. juin 27 15:17:36 CEST 2017

只执行第一个mpirun命令,之后的所有内容都不会执行。此行为直接使用subprocess.Popen重现,请参阅下面的示例代码:

from subprocess import *
from IPython.utils import py3compat
def test(s):
    p = Popen(['bash'], stdout=PIPE, stderr=PIPE, stdin=PIPE)
    out, err = p.communicate(s.encode('utf8', 'replace'))
    print(py3compat.bytes_to_str(out))
test("""echo "First"
mpirun -np 2 date
echo "Second"
mpirun -np 2 date
echo "End" """)

我可能遗漏了一些东西,但Popen似乎在第一个mpirun之后停止执行每个命令。当所有内容都放在一行上时,我得到了预期的结果,但对于一个IPython魔法单元来说它并不是很有趣:

test("""echo "First"; mpirun -np 2 date; echo "Second";mpirun -np 2 date; echo "End" """)

关于Popen挂起的原因的任何想法? 感谢您的反馈。

(在Linux上测试过,使用Python-2.7.13和IPython-5.4.1以及使用Python 3.6.1和IPython 6.1.0并使用几个版本的OpenMPI-1.10.x和2.1.x)

1 个答案:

答案 0 :(得分:0)

除了shell之外你还需要bash吗?你能使用shell = True Popen选项并将你的命令串直接传递给Popen吗?这样对我来说:

commands = """mpirun -np 2 date
mpirun -np 2 date
mpirun -np 2 date"""
p = Popen(commands, stdout=PIPE, stderr=PIPE, stdin=PIPE, shell=True)
p.stdout.read()
'Thu Jun 29 00:41:16 UTC 2017\nThu Jun 29 00:41:16 UTC 2017\nThu Jun 29 00:41:16 UTC 2017\nThu Jun 29 00:41:16 UTC 2017\nThu Jun 29 00:41:16 UTC 2017\nThu Jun 29 00:41:16 UTC 2017\n'