简体   繁体   中英

Python subprocess git checkout returns error even if there is no error

I am writing a script to automate some GIT tasks. I know about GITPython but I prefer not using that. Even tough it may be easier.

I got the following piece of code:

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)

This piece of code given the command ['git', 'checkout', 'master'] does indeed checkout the master. BUT it will stop executing, apparently because the error variable is not empty. I tried to print the outputs on error which is the following:

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

As you can see, it succesfully checked out the master branch (Also verified by git status ). But why is the second line filled in the error variable? How to handle this? Or is there no way of correctly handling this? Or should i not do any error checking? What is the best solution/explaination for this?

Thanks!

Its not an error ! its the output on stderr :)

If you are on a linux terminal, you can test this by running the following

git checkout master 2>/dev/null

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

According to subprocess docs

communicate() returns a tuple (stdoutdata, stderrdata)

ie the output on stdout and stderr.

If you want to check for errors, you should use the returncode attribute.

in your case

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)

algrebe answer is the right answer for your question, but this might help you.

Idea is to use try-except for execution and poll for checking if error occured. With some error handling and format of response (git returns string with \\n character for new line and that's how it's written in console) you get generic function that handles all git commands.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM