Python 读取git克隆';s实时输出
我需要读取git克隆进程的状态(接收对象XXX%),但不知道如何读取 我正在使用subprocess.Popen,但我不知道如何获取我需要的行: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
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中是这样)上迭代。谢谢,我尝试了这个,但似乎不起作用,输出似乎是原始的