【问题标题】:Curl is generating status 400 in subprocessCurl 在子进程中生成状态 400
【发布时间】:2021-09-18 08:32:19
【问题描述】:

我在 Windows 命令行提示符下运行 curl 命令。它产生json 输出。该命令如下所示:

curl --data "action=details&user=user&project=project1&problemid=2021" https://website:9020/

我在 python 中发出相同的命令如下:

import subprocess
output = subprocess.run(
                [
                    "curl",
                    "--data",
                    "\"action=details&user=user&project=project1&problemid=2021\""
                    "https://website:9020/",
                ],
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                shell=True,
            )
print(output.stdout.decode("utf-8"))

输出如下:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   199  100    64  100   123     64    123  0:00:01 --:--:--  0:00:01  1254
{"status":400,"message":"Action parameter is missing"}

但是命令行会产生一个 json 输出。然而,通过subprocess.run 发出的相同命令会产生此错误。我还用subprocess.Popensubprocess.check_output 进行了尝试。同样的问题仍然存在。我在这里做错了什么导致此错误?

【问题讨论】:

    标签: python python-3.x curl subprocess


    【解决方案1】:

    在某些情况下(例如,如果他们需要以管理员身份运行命令行),subprocess 可能不是执行命令行命令的正确选择。

    您可以使用os.system() 查看输出或使用os.popen() 读取和存储输出。

    import os
    import json
    
    # to see the output 
    print(os.system("curl --data \"action=details&user=user&project=project1&problemid=2021\" https://website:9020/")
    
    output = os.popen("curl --data \"action=details&user=user&project=project1&problemid=2021\" https://website:9020/").read()
    
    outputjson = json.loads(output)
    

    然后您可以访问json 信息。

    【讨论】:

    • 您会注意到os.system 文档建议您改用subprocess,而os.popen 只是subprocess 周围的一个薄且基本上冗余的包装器。
    • 但这对我不起作用。 os.popen 做到了。
    【解决方案2】:

    您是否尝试过在 action 参数周围不加引号的情况下运行代码?因为 API 抱怨缺少操作参数。我认为它只是由于转义引号而无法识别它。

    import subprocess
    output = subprocess.run(
        [
            "curl",
            "--data",
            "action=details&user=user&project=project1&problemid=2021"
            "https://website:9020/",
        ],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        shell=True,
    )
    print(output.stdout.decode("utf-8"))
    

    编辑:我不确定是否是这种情况,但可能是子进程隐式地用引号将其所有参数括起来,以避免代码注入和通配。

    我只是再次谷歌搜索并找到this answer,它说得很好:如果可以使用请求,为什么要使用curl?

    不保证,但我认为这样的事情应该有效:

    import requests
    url = "https://website:9020/"
    payload = {
        "action": "details",
        "user": "user",
        "project": "project1",
        "problemid": "2021"
    }
    res = requests.get(url, params=payload)
    

    【讨论】:

    • 不,恰恰相反。在 shell 中运行命令时,需要引用数据以保护其不被 shell 修改;但是这里你没有 shell,所以引号不仅没有必要,而且是错误的。
    • 是的,没有引号就不行。如果我在没有它们的情况下运行,它会说“动作”不被识别为内部命令。 curl 不会自动将参数用引号括起来。
    • 这在When to wrap quotes around a shell variable? 中有更详细的解释,但同样,这个答案是正确的,而不是编辑中的推测。我猜“隐含地”让它有点正确,但不是真的。
    • 等等,shell=True 在这里大错特错。
    • @tripleee 应该是假的吗?或者那个选项根本不应该存在?我都试过了,但错误仍然存​​在。
    猜你喜欢
    • 2020-08-18
    • 2014-08-24
    • 2021-11-29
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    • 2020-12-13
    相关资源
    最近更新 更多