【问题标题】:python - subprocess call not terminating when using pipespython - 使用管道时子进程调用未终止
【发布时间】:2010-12-24 17:16:45
【问题描述】:

我对 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()”需要一分钟或更长时间才能完成。如果接口之前是up,程序运行顺利。我从命令行手动测试了两种情况下的“ifup eth0”,而且速度很快。

如果您知道问题可能是什么,我将不胜感激。

提前致谢

编辑:

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

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

如果界面之前已经启动,则脚本运行顺畅。但是,如果接口关闭,python 会再次挂起。我也试过了:

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

而且一切都运行得非常快。因此,正如 funktku 指出的那样,它可能确实与死锁有关。然而python文档也说python ref:

警告

这会在使用的时候死锁 stdout=PIPE 和/或 stderr=PIPE 和 子进程产生足够的输出 到管道,使其阻塞等待 让操作系统管道缓冲区接受更多 数据。使用communicate() 来避免这种情况。

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

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

ifup eth0
Interface eth0 already configured

2案例,接口down之前:

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 的管道行为吗?

感谢每一个提示,在此先感谢

【问题讨论】:

  • 我还是有这个问题:-(

标签: python linux performance subprocess


【解决方案1】:

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

警告

像 Popen.wait() 一样,这将 使用 stdout=PIPE 和/或时出现死锁 stderr=PIPE 和子进程 为管道生成足够的输出,例如 它阻止等待操作系统管道 缓冲区以接受更多数据。

【讨论】:

  • 您能在回答中引用警告吗?外部页面的内容会随着时间而改变。
  • 非常感谢您的回答,但是根据我所做的测试,僵局不应该是我在帖子编辑中解释的问题。如果您有更多想法,我将非常感谢您的来信。谢谢
【解决方案2】:

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

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

【讨论】:

  • 哇,已经三年了,但这可以解释问题。非常感谢!
【解决方案3】:
p = subprocess.Popen(["ifup", "eth0"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()

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

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

【讨论】:

  • 非常感谢您的回答,您完全正确,我不需要 schell = True。然而不幸的是,上面的代码不起作用。 Python 仍然挂断。请参阅我添加到帖子中的附加部分...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2011-01-21
相关资源
最近更新 更多