即使没有错误,Python子进程git checkout也会返回错误

时间:2016-11-17 11:04:33

标签: python git subprocess

我正在编写一个脚本来自动执行一些GIT任务。我知道GITPython但我更喜欢不使用它。即使是艰难也可能更容易。

我得到了以下代码:

def executeCommand(cmd):
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
    out, error = p.communicate()
    if not error:
        return out.strip()
    else:
        print repr(out)
        print repr(error)
        print "Stopping execution!\r"
        exit(0)

给出命令['git', 'checkout', 'master']的这段代码确实检查了主人。但它会停止执行,显然是因为错误变量不为空。我试图打印出错误的输出,如下所示:

"Your branch is up-to-date with 'origin/master'.\n"
"Switched to branch 'master'\n"
Stopping execution!

如您所见,它成功检出了主分支(也由git status验证)。但为什么第二行填入错误变量?怎么办呢?或者没有办法正确处理这个?或者我不应该做任何错误检查?对此最好的解决方案/解释是什么?

谢谢!

2 个答案:

答案 0 :(得分:5)

这不是错误!它在stderr上的输出:)

如果您使用的是Linux终端,可以通过运行以下

进行测试
git checkout master 2>/dev/null

# You shouldn't see any output. 
# This is because git is writing those messages to stderr.

根据subprocess docs

  

communic()返回一个元组(stdoutdata,stderrdata)

即。 stdout和stderr上的输出。

如果要检查错误,应使用returncode属性。

在你的情况下

stdout, stderr = p.communicate()
if p.returncode == 0:
    return stdout.strip()

else:
    # handle error
    print repr(stdout)
    print repr(stderr)
    print "stopping execution!\r"
    exit(0)

答案 1 :(得分:2)

algrebe回答是您问题的正确答案,但这可能会对您有所帮助。

想法是使用try-except执行和poll来检查是否发生错误。 通过一些错误处理和响应格式(git为新行返回带有\ n字符的字符串以及它在控制台中的编写方式),您将获得处理所有git命令的通用函数。

class GitError(Exception):
    def __init__(self, value):
        self.value = format_rows(value)

    def __str__(self):
        return repr(self.value)


def execute(command, return_response=False):
    with Popen(command, shell=True, stdout=PIPE, stderr=PIPE) as process:
        try:
            response, error = process.communicate()
        except:
            process.kill()
            raise GitError('Fatal: Cannot execute command.')

        if process.poll():
            raise GitError(get_decoded_lines(error))

        if return_response:
            return format_rows(get_decoded_lines(response))


def get_decoded_lines(output):
    return output.decode().splitlines()


def format_rows(formatted_lines):
    return '\n'.join(formatted_lines)