从子流程获取进度消息

发布于 2024-10-16 20:11:52 字数 275 浏览 0 评论 0原文

我想启动一个需要几分钟才能完成的程序。在此期间,我想读取程序的进度消息(打印在标准输出上)。问题是我找不到在运行期间读出其输出的方法。

我发现读取程序输出的唯一函数是 Popen.communicate(),但此方法会等到进程完成。因此不可能获取进度并以特殊格式的方式让用户可见。

是否可以用另一种方式做到这一点?

当我使用脚本使用 subprocess.popen 运行该进程时,我在屏幕上看到了程序的输出。可以隐藏吗? (Ubuntu 10.10,普通终端)

I want to start a program which needs several minutes to complete. During this time I want to read the progress message of the program (which are printed on the stdout). The problem is that I cannot find a way to read out its output during its run.

The only function I found to read out the output of a program is Popen.communicate(), but this method waits until the process finishes. So it is impossible to get the progress and make it visible to the user in a special formatted way.

Is it possible to do this another way?

When I run the process with subprocess.popen with my script I see the output of the program on the screen. Is it possible to hide it? (Ubuntu 10.10, normal terminal)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蓝戈者 2024-10-23 20:11:52

最简单的是使用关键字参数 stdout=subprocess.PIPE 调用 Popen。

p = subprocess.Popen(["ls"], stdout=subprocess.PIPE)
while True:
    line = p.stdout.readline()
    if not line:
        break
    print line

要查看其实际效果,这里有两个示例脚本。将它们放在同一目录中并运行 python superprint.py

printandwait.py:

import time
import sys
print 10
sys.stdout.flush()
time.sleep(10)
print 20
sys.stdout.flush()

superprint.py:

import subprocess
import sys
p = subprocess.Popen(["python printandwait.py"], shell=True, stdout=subprocess.PIPE)
while True:
    print "Looping"
    line = p.stdout.readline()
    if not line:
        break
    print line.strip()
    sys.stdout.flush()

Simplest is to call Popen with the keyword argument stdout=subprocess.PIPE.

p = subprocess.Popen(["ls"], stdout=subprocess.PIPE)
while True:
    line = p.stdout.readline()
    if not line:
        break
    print line

To see this in action, here are two sample scripts. Make them both in the same directory and run python superprint.py

printandwait.py:

import time
import sys
print 10
sys.stdout.flush()
time.sleep(10)
print 20
sys.stdout.flush()

superprint.py:

import subprocess
import sys
p = subprocess.Popen(["python printandwait.py"], shell=True, stdout=subprocess.PIPE)
while True:
    print "Looping"
    line = p.stdout.readline()
    if not line:
        break
    print line.strip()
    sys.stdout.flush()
可可 2024-10-23 20:11:52

您可以对子流程的状态进行轮询并继续输出行。

p = subprocess.Popen('ls;sleep 10', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

rc = p.poll()
while rc != 0:
    while True:
        line = p.stdout.readline()
        if not line:
            break
        print line
    rc = p.poll()

assert rc == 0

You can do a poll on the status of your subprocess and keep outputting lines.

p = subprocess.Popen('ls;sleep 10', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

rc = p.poll()
while rc != 0:
    while True:
        line = p.stdout.readline()
        if not line:
            break
        print line
    rc = p.poll()

assert rc == 0
将军与妓 2024-10-23 20:11:52

这当然是可能的:我的包 python-gnupg 确实如此这会在子进程下生成 gpg (Gnu Privacy Guard)。一般情况下,您需要为子进程 stdout 和 stderr 指定 subprocess.PIPE ;然后创建两个单独的线程,将子进程的 stdout 和 stderr 读取到您喜欢的任何位置。

对于python-gnupg,在gpg进程运行时读取来自gpg的状态消息并采取行动(而不是等到它完成)。

基本上,伪代码是

process = subprocess.Popen(..., stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stderr = process.stderr
rr = threading.Thread(target=response_reader_func, args=(process.stderr,))
rr.setDaemon(True)
rr.start()

dr = threading.Thread(target=data_reader_func, args=(process.stdout,))
dr.setDaemon(True)
dr.start()

dr.join()
rr.join()
process.wait()

阅读器函数通常是封闭类的方法,它们根据正在阅读的内容执行正确的操作(在您的情况下,以某种方式更新进度信息)。

It's certainly possible: my package python-gnupg does exactly this, spawning gpg (Gnu Privacy Guard) under a subprocess. In the general case you need to specify subprocess.PIPE for the subprocess stdout and stderr; then create two separate threads which read the subprocess stdout and stderr to wherever you like.

In the case of python-gnupg, status messages from gpg are read and acted upon while the gpg process is running (not waiting until it's finished).

Basically, pseudocode is

process = subprocess.Popen(..., stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stderr = process.stderr
rr = threading.Thread(target=response_reader_func, args=(process.stderr,))
rr.setDaemon(True)
rr.start()

dr = threading.Thread(target=data_reader_func, args=(process.stdout,))
dr.setDaemon(True)
dr.start()

dr.join()
rr.join()
process.wait()

The reader functions are typically methods of an enclosing class which do the right thing based on what they're reading (in your case, updating progress info in some way).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文