subprocess.run 未能执行 运行 命令

subprocess.run failing to run command

我将这个字符串传递给 subproccess.run 并按空格拆分。

这就是我构建字符串的方式

patch_request = f"""/usr/local/bin/kubectl patch secret {secret_name} --type="json" -p='[{{"op":"replace","path":"/data/{k}","value":"{v}"}}]'"""

它产生

/usr/local/bin/kubectl patch secret beta --type="json" -p=\'[{"op":"replace","path":"/data/foo","value":"mock_value"}]\'

我最终得到了这个错误。知道可能出了什么问题吗?

CompletedProcess(args=['/usr/local/bin/kubectl', 'patch', 'secret', 'beta', '--type="json"', '-p=\'[{"op":"replace","path":"/data/foo","value":"mock_value"}]\''], returncode=1, stdout='', stderr='error: --type must be one of [json merge strategic], not "\"json\""\n')

将命令构建为数组以发送到 subprocess.run 而不是进行字符串替换一开始会稍微多一些工作,但稍后在需要有条件地添加、更改参数和选项时会提供更大的灵活性,等。我会这样设置:

    secret_name = "foo"
    k = 'K1'
    v = 'Dragon\'s "lair"'

    print(v)  # This will come out as  Dragon's "lair"  Note no backslash

    # Set up the baseline command that does not change a lot:                                                         
    cmd = ['/usr/local/bin/kubectl','patch','secret',secret_name,'--type=json']                                      
    
    #  Set up the more variable bits as a regular dict, not JSON. This gives
    #  you great control over setting up the data without worrying about
    #  formatting it into the final JSON representation:                                                     
    parg = {'op':'replace', 'path':'/data/%s' % k}

    # Example of flexibility in complex arg setup -- and note we do not have
    # to worry about the single and double quotes in v:
    parg['value'] = v    

    #  Now, "at the end", turn the more complex args into JSON.  This will, among                                     
    #  other things, take care of args that themselves contain single and double                                      
    #  quotes and other chars that complicate rendering to JSON:                                                      
    cmd.append('-p=%s' % json.dumps(parg))

    #  Run subprocess as a cmd array, not through the shell:                                                          
    p1 = subprocess.run(cmd, text=True, capture_output=True)
    print(p1.stdout)