简体   繁体   English

在Python子进程中使用反向标记

[英]Using back-ticks in Python subprocess

I want to run this git command through a Python script and get the output of it: 我想通过Python脚本运行这个git命令并获取它的输出:

git diff --name-only mybranch `git merge-base mybranch develop`

The purpose of the command is to see what changes have been made on mybranch since the last merge with develop. 该命令的目的是查看自上次与develop合并以来对mybranch所做的更改。

To achieve this I'm using subprocess.Popen : 为了实现这一点,我使用subprocess.Popen

output = subprocess.Popen(["git", "diff", "--name-only", "mybranch", "`git merge-base mybranch develop`"], stdout=subprocess.PIPE, shell=True)

However, this does not work. 但是,这不起作用。 The variable output.communicate()[0] simply gives me a printout of git usage -- essentially telling me the input command is wrong. 变量output.communicate()[0]只是给我一个git用法的打印输出 - 基本上告诉我输入命令是错误的。

I saw that a similar question exists here , but it only told me to use shell=True which didn't solve my problem. 我看到这里存在类似的问题,但它只告诉我使用shell=True ,但这并没有解决我的问题。

I also attempted to run the two commands in succession, but that gave me the same output as before. 我也试图连续运行这两个命令,但这给了我与以前相同的输出。 It is possible that I am missing something in this step, though. 但是,我可能在这一步中遗漏了一些东西。

Any help or tips are appreciated. 任何帮助或提示表示赞赏。

Backticks and subprocess 反引号和子进程

The backtick being a shell feature , you may not have a choice but to use shell=True , however pass in a shell command string , not a list of args 反引号是一个shell功能 ,你可能没有选择但是使用shell=True ,但是传入一个shell命令字符串 ,而不是一个args列表

So for your particular 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)

Notice when you call Popen() you get a process, shouldn't be called output IMO 注意当你调用Popen()你得到一个进程,不应该被称为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 $(cmd) 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 backticks) 这是不起作用的(用于反叛)

>>> 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'

On POSIX, the argument list is passed to /bin/sh -c ie, only the first argument is recognized as a shell command ie, the shell runs git without any arguments that is why you see the usage info. 在POSIX上,参数列表传递给/bin/sh -c ie,只有第一个参数被识别为shell命令,即shell运行git而没有任何参数,这就是为什么你会看到使用信息。 You should pass the command as a string if you want to use shell=True . 如果要使用shell=True则应将该命令作为字符串传递。 From the subprocess docs : subprocess文档

On POSIX with shell=True , the shell defaults to /bin/sh . 在POSIX上, shell=True ,shell默认为/bin/sh If args is a string, the string specifies the command to execute through the shell. 如果args是一个字符串,则该字符串指定要通过shell执行的命令。 This means that the string must be formatted exactly as it would be when typed at the shell prompt. 这意味着字符串的格式必须与在shell提示符下键入时完全相同。 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. 如果args是一个序列,则第一个项指定命令字符串,并且任何其他项将被视为shell本身的附加参数。 That is to say, Popen does the equivalent of: 也就是说, Popen相当于:

 Popen(['/bin/sh', '-c', args[0], args[1], ...]) 

You don't need shell=True in this case. 在这种情况下,您不需要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])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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