为Python subprocess.Popen打印执行的命令

时间:2012-02-07 14:11:48

标签: python

我有一个脚本可以自动在多个git存储库上重写作者。

def filter_history(old, new, name, repoPath):

command = """--env-filter '
        an="$GIT_AUTHOR_NAME"
        am="$GIT_AUTHOR_EMAIL"
        cn="$GIT_COMMITTER_NAME"
        cm="$GIT_COMMITTER_EMAIL"

        if [[ "$GIT_COMMITTER_NAME" = "|old|" ]]
        then
            cn="|name|"
            cm="|new|"
        fi

        if [[ "$GIT_AUTHOR_NAME" = "|old|" ]]
        then
            an="|name|"
            am="|new|"
        fi

        export GIT_AUTHOR_NAME="$an"
        export GIT_AUTHOR_EMAIL="$am"
        export GIT_COMMITTER_NAME="$cn"
        export GIT_COMMITTER_EMAIL="$cm"
'
"""

#DO string replace
command = command.replace("|old|", old)
command = command.replace("|new|", new)
command = command.replace("|name|", name)

print "git filter-branch -f " + command

process = subprocess.Popen(['git filter-branch -f', command],cwd=os.path.dirname(repoPath), shell=True)
process.wait()

该命令执行正常,但告诉我在回购历史中没有任何变化。但是,如果我接受打印出来的命令(应该是正在执行的命令),将其放在shell脚本中并执行它,它会改变历史记录。我认为该命令在某种程度上没有被正确执行。有没有办法确切地看到子进程模块正在执行什么命令?

1 个答案:

答案 0 :(得分:5)

使用shell = True时,subprocess.Popen需要一个字符串作为其第一个参数。如果可以提供帮助,最好不要使用shell = True,因为它可以是security risk (see the Warning

当您省略shell = True或使用shell = False时,subprocess.Popen需要一个参数列表。您可以使用shlex.split

从字符串生成参数列表
import shlex
import subprocess

def filter_history(old, new, name, repoPath):
    """Change author info
    """
    # http://help.github.com/change-author-info/
    # http://stackoverflow.com/a/3880493/190597
    command = """git filter-branch -f --env-filter '
        an="$GIT_AUTHOR_NAME"
        am="$GIT_AUTHOR_EMAIL"
        cn="$GIT_COMMITTER_NAME"
        cm="$GIT_COMMITTER_EMAIL"

        if [[ "$GIT_COMMITTER_NAME" = "{old}" ]]
        then
            cn="{name}"
            cm="{new}"
        fi

        if [[ "$GIT_AUTHOR_NAME" = "{old}" ]]
        then
            an="{name}"
            am="{new}"
        fi

        export GIT_AUTHOR_NAME="$an"
        export GIT_AUTHOR_EMAIL="$am"
        export GIT_COMMITTER_NAME="$cn"
        export GIT_COMMITTER_EMAIL="$cm"
      '
      """.format(old = old, new = new, name = name)

    process = subprocess.Popen(
        shlex.split(command),
        cwd = os.path.dirname(repoPath))
    process.communicate()