实时读取git clone的输出

时间:2014-04-18 13:45:27

标签: python

我需要读取git clone进程的状态(接收对象XXX%),但无法弄清楚如何。

我正在使用subprocess.Popen,但我无法弄清楚如何获取我需要的行:

proc = subprocess.Popen([GIT, "-C",IDIR+"/"+REPO,"clone",URL],shell=False,bufsize=0,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)

这是典型的输出:

Cloning into 'xxx'...
remote: Reusing existing pack: 5250, done.
remote: Counting objects: 1652, done.
remote: Compressing objects: 100% (1428/1428), done.
remote: Total 6902 (delta 389), reused 0 (delta 0)
Receiving objects: XXX% (6902/6902), 27.66 MiB | 1.51 MiB/s, done.
Resolving deltas: 100% (2010/2010), done.
Checking connectivity... done.
Checking out files: 100% (3266/3266), done.

修改

我已经在这个帖子和建议的副本中尝试了所有的建议,但似乎都没有。

这个建议导致“克隆到'测试'......完成”但没有其他输出:

popen = subprocess.Popen(["git", "clone", "https://github.com/xxx/test.git"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT,shell=False )
for line in popen.stdout:
  print "out newline:"
  print line
print "done"

这是不包含任何统计数据的输出:

out newline:
Cloning into 'test'...

done

5 个答案:

答案 0 :(得分:3)

[根据评论编辑] 使用git clone标志调用--progress会重定向输出。

这适合我。

import subprocess

popen = subprocess.Popen(["git", "clone", "--progress", "git@bitbucket.org:xxx/yyy.git"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in popen.stdout:
    print line,

print "done"

提供输出

$ python test.py 
Cloning into 'yyy'...
remote: Counting objects: 1076, done.
remote: Compressing objects: 100% (761/761), done.
remote: Total 1076 (delta 488), reused 576 (delta 227)
Receiving objects: 100% (1076/1076), 6.24 MiB | 260.00 KiB/s, done.
Resolving deltas: 100% (488/488), done.
Checking connectivity... done.
done

[编辑] 就像Cristian Ciupitu所指出的那样,iter() for line in popen.stdout:只是{{1}}也是如此(或者不依赖于版本)。

答案 1 :(得分:0)

我假设您希望实时通信在流程仍在运行时显示某种进度。

问题是正常的stdout流是缓冲的。你需要的是无缓冲的流。您可以使用os模块获取它,例如:

  fd = proc.stdout.fileno()
  while proc.returncode is None:
      l = os.read(fd, 1000)   # Read a bit of data
      print l

答案 2 :(得分:0)

我认为subprocess.communicate()应该可以解决问题。

我通常这样做:

process=subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdoutput,stderror=process.communicate()
for line in stdoutput:
    if line.startswith('Receiving objects'):
        print line

答案 3 :(得分:0)

首先,我建议将stdout和stderr组合在一起,即将{strong> Popen 与stderr=subprocess.STDOUT一起调用。

其次,您需要使用--progress执行 git ,因为git-clone man page说:

  

- 进度

Progress status is reported on the standard error stream by default when
it is attached to a terminal, unless -q is specified.  This flag forces
progress status even if the standard error stream is not directed to a
terminal.

并且您的git未附加到终端。

所以代码应如下所示:

popen = subprocess.Popen(["git", "clone", "--progress", url],
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT)
for line in popen.stdout:
  print "out newline:"
  print line
print "done"

我建议您阅读"Getting realtime output using subprocess"问题的答案,以改善您的计划。

答案 4 :(得分:0)

在描述了stderr--progress的其他响应上加上标记,下面是一个完整的最小工作示例,它将实时打印git clone命令:

import os
import re
import subprocess

def test():

    url = 'http://github.com/octocat/Hello-World/'

    output = subprocess.Popen(['git', 'clone', '--progress', url], stderr=subprocess.PIPE, stdout=subprocess.PIPE)

    fd = output.stderr.fileno()
    while True:
        lines = os.read(fd,1000).decode('utf-8')
        lines = re.split('\n|\r', lines)
        for l in lines:
            if l != '':
                print(l)
        if len(lines) == 1:
                break

    print('Press enter to continue.')