python - 使用管道时子进程调用不会终止

时间:2010-12-24 17:16:46

标签: python linux performance subprocess

我对python 2.6.5有一个奇怪的问题。如果我打电话

p = subprocess.Popen(["ifup eth0"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()

接口eth0关闭,python程序挂起。 “p.communicate()”需要一分钟或更长时间才能完成。如果接口之前已启动,则程序运行平稳。我在命令行中手动测试了“ifup eth0”这两种情况及其闪电速度。

如果你知道问题可能是什么,我会非常感激。

提前致谢

修改

根据答案,我尝试了以下方法:

p = subprocess.Popen(["ifup", "eth0"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()

如果之前接口已启动,则skript运行顺利。但是如果接口关闭,python会再次挂起。我也尝试过:

p = subprocess.Popen(["ifup", "eth0"], shell=False)
out, err = p.communicate()

一切都快速完成。因此,它可能确实与死锁有关,正如funktku所指出的那样。但是python文档也说python ref

  

警告

     

使用时会死锁   stdout = PIPE和/或stderr = PIPE和   子进程生成足够的输出   到管道,以阻止等待   为OS管道缓冲区接受更多   数据。使用communic()来避免这种情况。

因此不应该出现死锁。嗯......这是我在命令行上运行程序时的详细输出:

1个案例,接口eth0已经启动:

ifup eth0
Interface eth0 already configured

2案例,界面向下:

ifup eth0 
ssh stop/waiting
ssh start/running

因此ifup命令会在接口关闭前生成两行输出,否则生成一行输出。这是我注意到的唯一区别。但我怀疑这是问题的原因,因为“ls -ahl”会导致更多的输出线并且运行得非常好。

我也尝试过使用buffersize参数,但是没有成功,只需将它设置为像4096这样的大值。

你有想法,可能是什么原因造成的?或者这可能是python管道处理或ifup命令本身的错误?我真的必须使用旧的os.popen(cmd).read()????

EDIT2:

os.popen(cmd).read()遇到同样的问题。知道我如何在命令行上测试ifup的管道行为吗?

我很感激每一个提示,提前谢谢

3 个答案:

答案 0 :(得分:2)

您应该查看subprocess.call方法下的warning。这可能是您遇到问题的原因。

警告

  

与Popen.wait()一样,这样会   使用stdout = PIPE和/或时死锁   stderr = PIPE和子进程   为管道产生足够的输出   它阻止等待OS管道   缓冲区接受更多数据。

答案 1 :(得分:1)

p = subprocess.Popen(["ifup", "eth0"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()

设置shell=False,您不需要它。

尝试运行此代码,它应该工作。注意两个参数是如何在列表中单独的元素。

答案 2 :(得分:1)

/etc/network/if-up.d/ntpdate does not detach correctly

这就是为什么read()等到fds(stdin / stdout / stderr)关闭的原因。 你可以分离stdin / stderr / stdout(不要添加stdout = subprocess.PIPE和Popen构造函数调用相同)。