打印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脚本中并执行,它会很好地更改历史记录。我认为这个命令在某种程度上没有被正确执行。有没有什么方法可以让be确切地看到子流程模块正在执行什么命令?

使用shell = True时,subprocess.Popen需要一个字符串作为其第一个参数。如果可以的话,最好不要使用shell = True,因为它可能存在安全风险(请参阅警告.

当省略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()

如果您的应用程序在Windows环境中运行,如下面的回答所述,子流程有一个未记录的函数subprocess.list2cmdline,您可以使用它。subprocess.list2cmdline使用与MS C运行时相同的规则,将一系列参数转换为命令行字符串。

如果您正在使用Python>3.3您也可以使用.args:直接从子流程对象获取参数列表

import subprocess
process = subprocess.Popen(...)
subprocess.list2cmdline(process.args)

由于Python 3.8也有可能使用shlex.join()函数:

请记住,子进程通过IPC完成所有操作,因此最好的方法是简单地检查args列表,因为它们将被传递给被调用程序中的argv

最新更新