Python's Popen +communication 只返回标准输出的第一行 [英] Python's Popen + communicate only returning the first line of stdout

查看:66
本文介绍了Python's Popen +communication 只返回标准输出的第一行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用我的命令行 git 客户端和 Python 的 I/O 重定向,以便在许多 git 存储库上自动执行一些常见操作.(是的,这是 hack-ish.我以后可能会回去使用 Python 库来做这件事,但现在它似乎工作正常 :) )

I'm trying to use my command-line git client and Python's I/O redirection in order to automate some common operations on a lot of git repos. (Yes, this is hack-ish. I might go back and use a Python library to do this later, but for now it seems to be working out ok :) )

我希望能够捕获调用 git 的输出.隐藏输出会更好看,捕获它会让我记录它,以防它有用.

I'd like to be able to capture the output of calling git. Hiding the output will look nicer, and capturing it will let me log it in case it's useful.

我的问题是,当我运行git clone"命令时,我无法获得超过第一行的输出.奇怪的是,带有 'git status' 的相同代码似乎工作得很好.

My problem is that I can't get more than the first line of output when I run a 'git clone' command. Weirdly, the same code with 'git status' seems to work just fine.

我在 Windows 7 上运行 Python 2.7,我正在使用 cmd.exe 命令解释器.

I'm running Python 2.7 on Windows 7 and I'm using the cmd.exe command interpreter.

到目前为止我的侦探:

  1. 当我用git clone"调用 subprocess.call() 时它运行良好,我查看控制台上的输出(确认 git 正在生成输出,即使我没有捕获它).这段代码:

  1. When I call subprocess.call() with "git clone" it runs fine and I see the output on the console (which confirms that git is producing output, even though I'm not capturing it). This code:

dir = "E:\\Work\\etc\\etc"
os.chdir(dir)
git_cmd = "git clone git@192.168.56.101:Mike_VonP/bit142_assign_2.git"

#print "SUBPROCESS.CALL" + "="*20
#ret = subprocess.call(git_cmd.split(), shell=True) 

将在控制台上产生此输出:

will produce this output on the console:

SUBPROCESS.CALL====================
Cloning into 'bit142_assign_2'...
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 9 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (9/9), done.
Checking connectivity... done.

  • 如果我直接用 POpen 做同样的事情,我会看到同样的输出控制台(也没有被捕获).这段代码:

    # (the dir = , os.chdir, and git_cmd= lines are still executed here)
    print "SUBPROCESS.POPEN" + "="*20
    p=subprocess.Popen(git_cmd.split(), shell=True)
    p.wait()
    

    将产生这个(实际上相同的)输出:

    will produce this (effectively identical) output:

    SUBPROCESS.POPEN====================
    Cloning into 'bit142_assign_2'...
    remote: Counting objects: 9, done.
    remote: Compressing objects: 100% (4/4), done.
    remote: Total 9 (delta 0), reused 0 (delta 0)
    Receiving objects: 100% (9/9), done.
    Checking connectivity... done.
    

    (显然我会在两次运行之间删除克隆的存储库,否则我会收到一切都是最新的"消息)

    (Obviously I'm deleting the cloned repo between runs, otherwise I'd get a 'Everything is up to date' message)

    如果我使用communication()方法,我期望得到一个字符串包含我在上面看到的所有输出.相反我只看到这一行 克隆到'bit142_assign_2'....
    这段代码:

    If I use the communicate() method what I expect is to get a string that contains all the output that I'm seeing above. Instead I only see the line Cloning into 'bit142_assign_2'....
    This code:

    print "SUBPROCESS.POPEN, COMMUNICATE" + "="*20
    p=subprocess.Popen(git_cmd.split(), shell=True,\
                bufsize = 1,\
                stderr=subprocess.PIPE,\
                stdout=subprocess.PIPE)
    tuple = p.communicate()
    p.wait()
    print "StdOut:\n" + tuple[0]
    print "StdErr:\n" + tuple[1]
    

    将产生此输出:

    SUBPROCESS.POPEN, COMMUNICATE====================
    StdOut:
    
    StdErr:
    Cloning into 'bit142_assign_2'...
    

    一方面,我重定向了输出(正如您从事实中看到的那样)它不在输出中)但我也只捕获第一行.

    On the one hand I've redirected the output (as you can see from the fact that it's not in the output) but I'm also only capturing that first line.

    我尝试了很多很多东西(调用 check_output 而不是 popen,使用带有 subprocess.call 的管道,使用带有 subprocess.popen 的管道,以及我可能忘记的其他东西)但没有任何效果 - 我只捕获了第一行输出.

    I've tried lots and lots of stuff (calling check_output instead of popen, using pipes with subprocess.call, using pipes with subprocess.popen, and probably other stuff I've forgotten about) but nothing works - I only ever capture that first line of output.

    有趣的是,完全相同的代码确实可以与git status"一起正常工作.克隆存储库后,调用 git status 会生成三行输出(统称为一切都是最新的"),而第三个示例(POpen+communicate 代码)确实捕获了所有三行输出.

    Interestingly, the exact same code does work correctly with 'git status'. Once the repo has been cloned calling git status produces three lines of output (which collectively say 'everything is up to date') and that third example (the POpen+communicate code) does capture all three lines of output.

    如果有人对我做错了什么有任何想法,或者对我可以尝试以更好地诊断此问题的任何想法有任何想法,我将不胜感激.

    If anyone has any ideas about what I'm doing wrong or any thoughts on anything I could try in order to better diagnose this problem I would greatly appreciate it.

    推荐答案

    尝试将 --progress 选项添加到您的 git 命令中.这会强制 git 将进度状态发送到 stderr,即使 git 进程未连接到终端 - 这就是通过 subprocess 函数运行 git 时的情况.

    Try adding the --progress option to your git command. This forces git to emit the progress status to stderr even when the the git process is not attached to a terminal - which is the case when running git via the subprocess functions.

    git_cmd = "git clone --progress git@192.168.56.101:Mike_VonP/bit142_assign_2.git"
    
    print "SUBPROCESS.POPEN, COMMUNICATE" + "="*20
    p = subprocess.Popen(git_cmd.split(), stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    tuple = p.communicate()
    p.wait()
    print "StdOut:\n" + tuple[0]
    print "StdErr:\n" + tuple[1]
    

    注意我无法在 Windows 上对此进行测试,但它在 Linux 上有效.

    N.B. I am unable to test this on Windows, but it is effective on Linux.

    另外,没有必要指定shell=True,这可能是一个安全问题,所以最好避免.

    Also, it should not be necessary to specify shell=True and this might be a security problem, so it's best avoided.

    这篇关于Python's Popen +communication 只返回标准输出的第一行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆