【问题标题】:Print executed command for Python subprocess.Popen打印 Python subprocess.Popen 的执行命令
【发布时间】:2012-02-28 23:15:12
【问题描述】:

我有一个脚本可以自动在多个 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 脚本并执行它,它会很好地更改历史记录。我认为该命令在某种程度上没有正确执行。有什么办法可以查看子进程模块正在执行什么命令?

【问题讨论】:

    标签: python


    【解决方案1】:

    当您使用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()
    

    【讨论】:

      【解决方案2】:

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

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-08-24
        • 2016-12-30
        • 2021-12-31
        • 2019-08-02
        • 2015-05-23
        • 1970-01-01
        • 2010-12-12
        相关资源
        最近更新 更多