Using back-ticks in a Python subprocess
I want to run this git command through a Python script and get its output:
git diff --name-only mybranch `git merge-base mybranch develop`
The team's goal is to see what changes have been made mybranch
since the last merge during development.
For this I use subprocess.Popen
:
output = subprocess.Popen(["git", "diff", "--name-only", "mybranch", "`git merge-base mybranch develop`"], stdout=subprocess.PIPE, shell=True)
However, this doesn't work. The variable output.communicate()[0]
just gives me a printout of git usage - essentially telling me that the input command is wrong.
I saw a similar question exists here , but it only told me to use shell=True
, which didn't solve my problem.
I also tried running two commands in a row, but that gave me the same result as before. It is possible that I missed something at this stage.
Any help or advice is greatly appreciated.
source to share
Backticks and subprocess
Return is a shell , you may have no choice but to use shell=True
, however pass the command line string , not the argument list
So, for your specific command (assuming it works in the first place)
process = subprocess.Popen("git diff --name-only mybranch `git merge-base mybranch develop`", stdout=subprocess.PIPE, shell=True)
Please note that when called Popen()
you get a process, shouldn't be called output
IMO
Here's a simple example that works with backticks
>>> process = subprocess.Popen('echo `pwd`', stdout=subprocess.PIPE, shell=True)
>>> out, err = process.communicate()
>>> out
'/Users/bakkal\n'
Or you can use the syntax $ (cmd)
>>> process = subprocess.Popen('echo $(pwd)', stdout=subprocess.PIPE, shell=True)
>>> out, err = process.communicate()
>>> out
'/Users/bakkal\n'
Here's what did NOT work (for reverse steps)
>>> process = subprocess.Popen(['echo', '`pwd`'], stdout=subprocess.PIPE, shell=True)
>>> out, err = process.communicate()
>>> out
'\n'
>>> process = subprocess.Popen(['echo', '`pwd`'], stdout=subprocess.PIPE, shell=False)
>>> out, err = process.communicate()
>>> out
'`pwd`\n'
source to share
In POSIX, the argument list is passed /bin/sh -c
, i.e. only the first argument is recognized as a shell command, i.e. the shell starts up git
without any arguments, so you see usage information. You must pass the command as a string if you want to use shell=True
. From the subprocess
docs :
In POSIX
shell=True
, the default shell is/bin/sh
. Ifargs
is string, the string specifies the command to execute through the shell. This means that the string must be formatted exactly as it would be when typed on the command line. This includes, for example, quoting or backslashes skipping filenames with spaces in them. Ifargs
is a sequence, the first element indicates the command line, and any additional elements will be treated as additional arguments to the shell itself. That is, itPopen
performs the equivalent:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
In this case, you don't need to shell=True
.
#!/usr/bin/env python
from subprocess import check_output
merge_base_output = check_output('git merge-base mybranch develop'.split(),
universal_newlines=True).strip()
diff_output = check_output('git diff --name-only mybranch'.split() +
[merge_base_output])
source to share