在 Python 子流程中使用反引号
Using back-ticks in Python subprocess
我想通过 Python 脚本 运行 这个 git 命令并得到它的输出:
git diff --name-only mybranch `git merge-base mybranch develop`
该命令的目的是查看自上次与 develop 合并后 mybranch
发生了哪些变化。
为此,我使用 subprocess.Popen
:
output = subprocess.Popen(["git", "diff", "--name-only", "mybranch", "`git merge-base mybranch develop`"], stdout=subprocess.PIPE, shell=True)
但是,这不起作用。变量 output.communicate()[0]
只是给我一个 git 用法的打印输出——本质上告诉我输入命令是错误的。
我看到一个类似的问题,但它只告诉我使用shell=True
,并没有解决我的问题。
我也尝试连续 运行 这两个命令,但这给了我与以前相同的输出。不过,我可能在这一步中遗漏了一些东西。
如有任何帮助或提示,我们将不胜感激。
反引号和子进程
反引号是 shell 的一个特性,你可能别无选择,只能使用 shell=True
,但是传入 a shell 命令字符串,不是参数列表
因此对于您的特定命令(假设它首先起作用)
process = subprocess.Popen("git diff --name-only mybranch `git merge-base mybranch develop`", stdout=subprocess.PIPE, shell=True)
请注意,当您调用 Popen()
时,您会得到一个进程,不应调用 output
IMO
这是一个使用反引号的简单示例
>>> process = subprocess.Popen('echo `pwd`', stdout=subprocess.PIPE, shell=True)
>>> out, err = process.communicate()
>>> out
'/Users/bakkal\n'
或者您可以使用 $(cmd) 语法
>>> process = subprocess.Popen('echo $(pwd)', stdout=subprocess.PIPE, shell=True)
>>> out, err = process.communicate()
>>> out
'/Users/bakkal\n'
这是无效的(对于反引号)
>>> 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'
在 POSIX 上,参数列表被传递给 /bin/sh -c
即,只有第一个参数被识别为 shell 命令,即 shell 运行 git
没有任何参数,这就是您看到使用信息的原因。如果要使用 shell=True
,则应将命令作为字符串传递。来自 the subprocess
docs:
On POSIX with shell=True
, the shell defaults to /bin/sh
. If args
is a
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 at the shell prompt. This includes, for example, quoting or
backslash escaping filenames with spaces in them. If args
is a
sequence, the first item specifies the command string, and any
additional items will be treated as additional arguments to the shell
itself. That is to say, Popen
does the equivalent of:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
在这种情况下,您不需要 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])
我想通过 Python 脚本 运行 这个 git 命令并得到它的输出:
git diff --name-only mybranch `git merge-base mybranch develop`
该命令的目的是查看自上次与 develop 合并后 mybranch
发生了哪些变化。
为此,我使用 subprocess.Popen
:
output = subprocess.Popen(["git", "diff", "--name-only", "mybranch", "`git merge-base mybranch develop`"], stdout=subprocess.PIPE, shell=True)
但是,这不起作用。变量 output.communicate()[0]
只是给我一个 git 用法的打印输出——本质上告诉我输入命令是错误的。
我看到一个类似的问题shell=True
,并没有解决我的问题。
我也尝试连续 运行 这两个命令,但这给了我与以前相同的输出。不过,我可能在这一步中遗漏了一些东西。
如有任何帮助或提示,我们将不胜感激。
反引号和子进程
反引号是 shell 的一个特性,你可能别无选择,只能使用 shell=True
,但是传入 a shell 命令字符串,不是参数列表
因此对于您的特定命令(假设它首先起作用)
process = subprocess.Popen("git diff --name-only mybranch `git merge-base mybranch develop`", stdout=subprocess.PIPE, shell=True)
请注意,当您调用 Popen()
时,您会得到一个进程,不应调用 output
IMO
这是一个使用反引号的简单示例
>>> process = subprocess.Popen('echo `pwd`', stdout=subprocess.PIPE, shell=True)
>>> out, err = process.communicate()
>>> out
'/Users/bakkal\n'
或者您可以使用 $(cmd) 语法
>>> process = subprocess.Popen('echo $(pwd)', stdout=subprocess.PIPE, shell=True)
>>> out, err = process.communicate()
>>> out
'/Users/bakkal\n'
这是无效的(对于反引号)
>>> 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'
在 POSIX 上,参数列表被传递给 /bin/sh -c
即,只有第一个参数被识别为 shell 命令,即 shell 运行 git
没有任何参数,这就是您看到使用信息的原因。如果要使用 shell=True
,则应将命令作为字符串传递。来自 the subprocess
docs:
On POSIX with
shell=True
, the shell defaults to/bin/sh
. Ifargs
is a 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 at the shell prompt. This includes, for example, quoting or backslash escaping filenames with spaces in them. Ifargs
is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself. That is to say,Popen
does the equivalent of:Popen(['/bin/sh', '-c', args[0], args[1], ...])
在这种情况下,您不需要 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])