Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 读取git克隆';s实时输出_Python - Fatal编程技术网

Python 读取git克隆';s实时输出

Python 读取git克隆';s实时输出,python,Python,我需要读取git克隆进程的状态(接收对象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: Reus

我需要读取git克隆进程的状态(接收对象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

[根据评论进行编辑] 使用
--progress
标志调用
git clone
,将重定向输出ok

这对我有用

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指出的,popen中的行不需要
iter()
就可以
。stdout:
也可以工作(或者不取决于版本)。

[根据注释编辑] 使用
--progress
标志调用
git clone
,将重定向输出ok

这对我有用

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指出的那样,popen中的行不需要
iter()
就可以
。标准代码:
也可以工作(或者不取决于版本)。

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

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

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

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

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

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

我认为
子流程.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
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"

我认为
子流程.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
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"

首先,我建议将stdout和stderr结合起来,将所有内容放在一个地方,即使用
stderr=subprocess.stdout
调用Popen

其次,您需要使用
--progress
执行git,因为

--进展

并且您的git没有连接到终端

因此,代码应该如下所示:

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
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"

我建议阅读问题的答案以改进您的程序。

首先,我建议将stdout和stderr结合起来,使所有内容都集中在一个地方,即调用Popen
stderr=subprocess.stdout

其次,您需要使用
--progress
执行git,因为

--进展

并且您的git没有连接到终端

因此,代码应该如下所示:

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
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"

我建议您阅读问题的答案以改进您的程序。

根据描述了
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.')

下面是一个完整的最小工作示例,可以实时打印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.')


您使用
stdout=subprocess.PIPE
正确设置了子流程,因此现在可以通过
proc.stdout.readline()
proc.communicate()
获取流程的输出。在那之后,这只是一个字符串匹配或使用正则表达式的游戏。可能的重复我已经尝试了该线程中的所有建议,以及该线程中的建议,似乎都无法捕获输出。您仍在扫描
popen.stdout
而不是
popen.stderr
。为了避免任何进一步的问题,我还建议将stdout和stderr结合起来,即使用
stderr=subprocess.stdout
调用Popen。嗨,Christian,非常感谢您的耐心等待。我已经按照建议修改了代码,并用我测试的代码更新了主线程。现在我得到了输出“Cloning into'test'…”,后跟“done”,但没有其他状态输出。您使用
stdout=subprocess.PIPE
正确设置了子流程,因此现在您可以通过
proc.stdout.readline()
proc.communicate()
获取流程的输出。在那之后,这只是一个字符串匹配或使用正则表达式的游戏。可能的重复我已经尝试了该线程中的所有建议,以及该线程中的建议,似乎都无法捕获输出。您仍在扫描
popen.stdout
而不是
popen.stderr
。为了避免任何进一步的问题,我还建议将stdout和stderr结合起来,即使用
stderr=subprocess.stdout
调用Popen。嗨,Christian,非常感谢您的耐心等待。我已经按照建议修改了代码,并用我测试的代码更新了主线程。现在我得到的输出是“Cloning into'test'…”,后面是“done”,但其他状态输出都没有。这看起来不起作用。它如何知道何时停止迭代?@ebarr:输入不是以EOF字符结尾吗?您可以直接在
popen.stdout
(至少在Python 2.7中是这样)上迭代。谢谢,我尝试了这个方法,但似乎不起作用,输出似乎来自subprocess.popen()行,而不是“for line in..print”。即使我完全注释掉for循环,输出也是一样的。这是因为git的一些输出(例如,
克隆到…
)将转到stderr,而不是stdout。所以stderr也需要重定向。这看起来不起作用。它如何知道何时停止迭代?@ebarr:输入不是以EOF字符结尾吗?您可以直接在
popen.stdout
(至少在Python 2.7中是这样)上迭代。谢谢,我尝试了这个,但似乎不起作用,输出似乎是原始的