繁体   English   中英

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

[英]Print executed command for Python subprocess.Popen

我有一个脚本可以让作者在许多 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()

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

当您使用shell = Truesubprocess.Popen期望将字符串作为其第一个参数。 如果可以帮助,最好不要使用shell = True ,因为它可能会带来安全风险(请参阅Warning)

当省略shell = True或使用shell = Falsesubprocess.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 有一个未公开的函数subprocess.list2cmdline ,您可以使用它。 subprocess.list2cmdline使用与 MS C 运行时相同的规则将参数序列转换为命令行字符串。

如果您使用的是 Python > 3.3,您还可以使用.args直接从子.args对象获取 args 列表:

import subprocess

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

从 Python 3.8 开始,也可以使用shlex.join()函数:

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

暂无
暂无

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

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