如何让Python的subprocess函数执行shell命令时解析git分支命令?
问题:subprocess执行含命令替换的Bash命令时无法解析变量
我使用subprocess包编写了如下Python函数:
def run_sh(command): """Print output of bash command""" try: process = Popen(shlex.split(command), stdout=PIPE) for line in TextIOWrapper(process.stdout, newline=""): print(line) except CalledProcessError as e: raise RuntimeError( "command '{}' return with error (code {}): {}".format( e.cmd, e.returncode, e.output ) )
当调用run_sh("newman run MY_COLLECTION.json --env-var 'current_branch'=git branch --show-current")时,git branch --show-current没有被解析为实际的当前分支名称,而是被当作字符串直接传入newman命令,导致不符合预期。请问如何让Shell先解析命令替换后再执行?
解决方案
问题根源在于当前代码用shlex.split()拆分命令后直接通过Popen执行,没有让Shell介入处理命令替换(反引号`包裹的语法)。以下是两种可行解决方式:
方法1:修改函数启用Shell解析
在Popen中添加shell=True参数,让Bash负责解析命令中的替换逻辑,同时不再需要shlex.split()拆分命令:
def run_sh(command): """Print output of bash command""" try: # 启用shell让Bash处理命令替换,text=True直接按文本读取输出 process = Popen(command, stdout=PIPE, shell=True, text=True) for line in process.stdout: print(line.rstrip('\n')) except CalledProcessError as e: raise RuntimeError( "command '{}' return with error (code {}): {}".format( e.cmd, e.returncode, e.output ) )
注意:
shell=True存在Shell注入风险,若命令包含不可信输入,不建议使用该方式。
方法2:在Python中提前获取分支名(更安全)
避免依赖Shell解析,直接在Python中执行git命令获取分支名,再拼接成最终的newman命令。这种方式既安全,也更符合Python的处理逻辑:
import subprocess from subprocess import Popen, PIPE, CalledProcessError import shlex def run_sh(command): """Print output of bash command""" try: process = Popen(shlex.split(command), stdout=PIPE, text=True) for line in process.stdout: print(line.rstrip('\n')) except CalledProcessError as e: raise RuntimeError( "command '{}' return with error (code {}): {}".format( e.cmd, e.returncode, e.output ) ) # 先独立获取当前分支名 branch_name = subprocess.check_output(["git", "branch", "--show-current"], text=True).strip() # 拼接命令并执行 run_sh(f"newman run MY_COLLECTION.json --env-var 'current_branch'={branch_name}")
这种方式完全绕过Shell命令替换,既能保证分支名被正确解析,也规避了安全风险。
内容的提问来源于stack exchange,提问作者PianoTiger
相关产品推荐
相关产品推荐

