Python 子进程没有将大括号作为参数传递?或者双引号的问题

Python subprocess not passing curly brackets as arguments? Or a problem with double quotes

我对 python 子流程模块中的 } 括号和双引号有疑问。 这是标准终端命令的示例:

curl -X POST localhost:8080/employees -H 'Content-type:application/json' -d '{"name": "Luke Skywalker", "role": "Jedi"}'

当我尝试像这样使用子进程模块时: 1.

    test = subprocess.Popen(
        [
            "curl",
            "-X",
            "POST",
            "localhost:8080/employees",
            "-H",
            "'Content-type:application/json'",
            "-d",
            "'{",
            "name:",
            '"Luke Skywalker"',
            '"role:"',
            '"Jedi"',
            "}'",
        ],
        stdout=subprocess.PIPE,
    )
    output = test.communicate()[0]

我得到:


  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   126    0   124  100     2   4225     68 --:--:-- --:--:-- --:--:--  5727
curl: (3) URL using bad/illegal format or missing URL
curl: (3) URL using bad/illegal format or missing URL
curl: (3) URL using bad/illegal format or missing URL
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (6) Could not resolve host: "Jedi"
curl: (3) unmatched close brace/bracket in URL position 1:
}'
 ^

还有这个:

    test = subprocess.Popen(
       [
            "curl",
            "-X",
            "POST",
            "localhost:8080/employees",
            "-H",
            "'Content-type:application/json'",
            "-d",
            '\'{"name":',
            '"Luke Skywalker"',
            '"role:"',
            ' "Jedi"}\' ',
        ],
        stdout=subprocess.PIPE,
    )
    output = test.communicate()[0]

我得到:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   133    0   124  100     9   2699    195 --:--:-- --:--:-- --:--:--  3325
curl: (3) URL using bad/illegal format or missing URL
curl: (3) URL using bad/illegal format or missing URL
curl: (3) unmatched close brace/bracket in URL position 8:
 "Jedi"}' 
       ^

如有任何帮助,我们将不胜感激。提前致谢。

您需要了解 shell 是如何解析命令的。当你执行:

curl -X POST localhost:8080/employees -H 'Content-type:application/json' -d '{"name": "Luke Skywalker", "role": "Jedi"}'

curl 的参数是:-XPOSTlocalhost:8080/employees-HContent-type:application/json-d , 和 {"name": "Luke Skywalker", "role": "Jedi"}

shell 调用中单引号的作用是将整个字符串保留为文字参数,并防止它被空格分割。此外,它是一种在参数中传递双引号并防止它们被 shell 视为引号字符的机制。 Content-type:application/json 周围的单引号是不必要的,因为该字符串不包含 shell 的任何特殊字符,但通常的做法是像这样引用较长的字符串。为了文体的一致性,-H and POST and -X 甚至 curl 也应该被引用,但是大多数坚持“如果你不理解 shell" 风格很少采用那种程度的一致性。 curl 从来没有看到单引号,试图将它们传递到 Python 的参数列表中是一个错误。最初的 curl 命令也可以在 shell 中调用为:

'curl' "-X" PO""ST lo'cal'"host:8080/emp"loyees -"H" Content-type:application/json -d \{\"name\":\ \"Luke\ Skywalker\"\,\ \"role\":\ \"Jedi\"\}

shell 中的引用是(也许)值得研究一下以了解的东西。需要理解的重要一点是,(未转义的)引号(双引号和单引号,但每个引号的规则略有不同)被 shell 删除,因此被调用的应用程序永远不会看到它们。

请注意,我在引用上面有点轻率。引用字符串 Content-type:application/json 是完全合理的,因为不值得花时间来决定 :/ 是否对 shell 是特殊的。它们不是,但是 shell 实现中有足够的歧义,非常值得引用它们。例如,符合 posix 的 shell 将通过使用字符串 {a,b} 调用 cmd 来执行字符串 cmd {a,b},但是 bash(即使使用 - -posix) 将使用两个参数 ab 调用 cmd。这在这里是相关的,因为 json 包含一个 , 并且如果不引用该参数,则该参数将被不同的 shell 以不同方式解析。如有疑问,请使用引号。除非有特殊原因,否则请始终引用您的变量。

列表中的每一项都是调用进程的参数。您可以看到,您使用 'Content-type:application/json' 作为单个参数。同样,您也可以使用 json。

见下文:

payload = '{"name":"Luke Skywalker","role:"Jedi"}'
test = subprocess.Popen(
       [
            "curl",
            "-X",
            "POST",
            "localhost:8080/employees",
            "-H",
            "'Content-type:application/json'",
            "-d",
            f"'{payload}'"
        ],
        stdout=subprocess.PIPE,
    )
output = test.communicate()[0]

我把数据做了一个变量,所以你可以很容易地转义它。