python 为什么 subprocess.Popen(...) 不总是返回?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/694000/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 20:39:55  来源:igfitidea点击:

why doesn't subprocess.Popen(...) always return?

pythonsubprocess

提问by dF.

I hope this is a simple python question.

我希望这是一个简单的 Python 问题。

When I try the following in the python interpreter:

当我在 python 解释器中尝试以下操作时:

>>> import process
>>> def test(cmd):
...   p = subprocess.Popen(cmd)
...
>>> test(['ls', '-l'])

It will run the ls -l, but I need to hit "return" to get a new >>> prompt.

它将运行ls -l,但我需要点击“返回”以获得新的 >>> 提示。

However, when I try the following:

但是,当我尝试以下操作时:

>>> import process
>>> def test(cmd):
...   p = subprocess.Popen(cmd)
...   p.wait()
...
>>> test(['ls', '-l'])

Then the ls -lwill be run with a >>> prompt immediately present.

然后ls -l将立即出现 >>> 提示。

One other variation:

另一种变体:

>>> import process
>>> def test(cmd):
...   p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
...
>>> test(['ls', '-l'])

This will give me an immediate new prompt.

这将立即给我一个新的提示。

The last example is closest to what I want. My goal is to launch a child process, wait for it to finish and then use its stdout in my parent process by referring to p.stdoutwhile letting stderr just print to wherever it would otherwise.

最后一个例子最接近我想要的。我的目标是启动一个子进程,等待它完成,然后通过引用在我的父进程中使用它的 stdout,p.stdout同时让 stderr 只打印到其他地方。

Right now in my actual application, the last version just hangs at the: p = subprocess.Popen(cmd, stdout=subprocess.PIPE)with or without a p.wait().

现在在我的实际应用程序中,最后一个版本只是挂在: p = subprocess.Popen(cmd, stdout=subprocess.PIPE)有或没有p.wait().

Thanks,

谢谢,

Charlie

查理

回答by dF.

In the first variation, test()returns immediately after starting the process, but before its output is sent to the console.

在第一个变体中,test()在启动进程后立即返回,但在其输出发送到控制台之前。

If you look at the output you doget the prompt, immediately before the output of ls.

如果你看一下你的输出弹出提示,立即输出之前ls

>>> test(['ls', '-l'])
>>> total 0                            <----- test() returns, new propmpt
--rw-r--r--    1 foo bar   7 Mar 24 17:38
etc etc

In the second variation, test()is waiting for the process to terminate before it returns.

在第二个变体中,test()在返回之前等待进程终止。

In the third version, you're right that you may have to read from the child process's stdoutfor it to continue.

在第三个版本中,您可能必须从子进程中读取stdout才能继续。

回答by dF.

I may have answered my own question. I believe that in the final case, I need to explicitly read from p.stdout in order for my process to continue.

我可能已经回答了我自己的问题。我相信在最后一种情况下,我需要从 p.stdout 中明确读取,以便我的过程继续。

ie:

IE:

p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output = p.stdout.readlines()
....

Thanks all

谢谢大家

回答by user3273866

Just use communicate() method.No need to return.

只需使用communication() 方法。无需返回。

>>> test(['ls', '-l'])
>>> 
>>> def test(cmd):
...    p = subprocess.Popen(cmd).communicate()
... 
>>> test(['ls', '-l'])

回答by storm_m2138

Here is a command that pings Google forever, so it needs to be manually terminated to retrieve the output.

这是一个永远 ping Google 的命令,因此需要手动终止它以检索输出。

See the subprocess documentationfor instructions on converting os.popen() method calls to full subprocess.Popen classes.

有关将 os.popen() 方法调用转换为完整 subprocess.Popen 类的说明,请参阅子流程文档

host = "www.google.com"
command = "ping %s -t"%host

#p = os.popen(command) -- using Popen instead of os.popen() to allow calling terminate()
p = Popen(command, stdout=subprocess.PIPE)

time.sleep(5)
print "term"
p.terminate()
pingResultSoFar = p.communicate()[0] # get what has been printed to standard out so far
print pingResultSoFar