在Python中实时读取subprocess标准输出

4 投票
3 回答
2472 浏览
提问于 2025-04-17 01:46

我程序中的一个函数会检查一个文件的md5值。

def check():
    print "checking integrity status.."
    md5 = subprocess.Popen(["md5sum", "-c", hashfile],shell=False, stdout=subprocess.PIPE)
    #fopen = open(basefile, "r")
    for f in md5.stdout.readlines():
        fc = f.rstrip("\n")
        sys.stdout.write("\rChecking..." + fc)
        sys.stdout.flush()

现在的问题是,整个命令会先执行完,然后for循环再通过md5.stdout.readlines来读取md5的输出。这样就不是动态的,也就是说我不能在命令执行的时候就看到输出……有没有办法让我在命令执行的同时就能看到输出呢……

根据glglgl的回答解决了这个问题:

def check():
    print "checking integrity status.."
    md5 = subprocess.Popen(["md5sum", "-c", hashfile],shell=False, stdout=subprocess.PIPE)
    #fopen = open(basefile, "r")
    fc = "NULL"
    i = 0
    for f in iter(md5.stdout.readline, ''):
        k = fc
        fc = f.rstrip("\n")
        if "FAILED" in fc:
            print fc
        i = i + 1
        sys.stdout.write("\rChecking... "+ str(i)+ " " + fc + (' ' * (len(k) - len(fc))) )
        sys.stdout.flush()

3 个回答

0

文件大小是多少?

Popen会创建一个新的子进程来执行命令。可能在你运行循环之前,它就已经完成了。

你可以通过查看“subprocess”的返回码来检查它是否已经完成(在你的代码中是:md5.returncode)。

1

发帖的人说得对,hashlib这个库在Python 2.4里是没有的,不过md5这个库是可以用的。下面是一个解决方法的例子:

try:
        # Python 2.5 and up.
        import hashlib
        md5Hash = hashlib.md5

except ImportError:
        # Python 2.4 and below.
        import md5
        md5Hash = md5.new

somedata = 'foobar'
hashstring = md5Hash (somedata).hexdigest ()
5

当然可以。有几种方法可以做到这一点。

  1. 首先,你可以使用 md5.stdout.read(),不过这样的话你需要自己处理每一行的分隔。

  2. 接着,你可以把文件对象 md5.stdout 当作一个迭代器来使用。但这里似乎有个缓冲的问题,也就是说你不会立刻得到结果。

  3. 还有一种方法是反复调用 md5.stdout.readline(),直到它返回 ''(空字符串)。

在这种情况下,第三种方法是比较推荐的;我建议你这样做:

...

for f in iter(md5.stdout.readline, ''):
    fc = f.rstrip("\n")
    sys.stdout.write("\rChecked " + fc)
    sys.stdout.flush()

我也修改了输出文本,因为只有在检查完成后才会有输出。

如果你想要的不是这样,而是希望每次输出都单独捕获,那你应该选择第一种方法。但这样会让事情变得更复杂。我会考虑一个解决方案,如果有人需要的话。

在这里,需要考虑以下几点:

  • read() 是阻塞的,所以最好一个字节一个字节地读取(这有点麻烦)。
  • 还有一个问题是,什么内容应该输出,以及什么时候应该有中间输出。

撰写回答