【问题标题】:How do I get POST "data" variable in python3.x without using CGI?如何在不使用 CGI 的情况下在 python3.x 中获取 POST“数据”变量?
【发布时间】:2014-08-29 13:53:31
【问题描述】:

当我尝试在 python3.x cgi 脚本中调用 cgi.FieldStorage() 时,我收到以下错误:

[Traceback: error in module x on line y]:
    cgi.FieldStorage()
File "/usr/lib64/python3.3/cgi.py", line 553, in __init__
    self.read_single()
File "/usr/lib64/python3.3/cgi.py", line 709, in read_single
    self.read_binary()
File "/usr/lib64/python3.3/cgi.py", line 731, in read_binary
    self.file.write(data)
TypeError: must be str, not bytes

如何从 ajax 调用中获取我的 POST data 变量?

ajax 调用示例:

function (param) {
    $.ajax({
       type: "POST",
       url: "/cgi-bin/mycgi.py/TestMethod",
       data: JSON.stringify({"foo": "bar"}),
       contentType: "application/json; charset=utf-8",
       dataType: "json",
       success: function (result) {
           alert("Success " + result);
       },
       error: function () {
           alert("Failed");
       }
    });
}

【问题讨论】:

  • 我对 jQuery 不熟悉,所以我会将其作为评论发布。试试contentType: "x-www-form-urlencoded"

标签: ajax post python-3.x encoding cgi


【解决方案1】:

在我的例子中,我 tcpdump -x -Xed 从 JavaScript 发送的数据并注意到正在发送 text/plainContent-type 标头。所以我按照推荐的here 将其设置为application/x-www-form-urlencoded 并解决了问题。

【讨论】:

    【解决方案2】:

    根据http://lucumr.pocoo.org/2013/7/2/the-updated-guide-to-unicode/

    "There are also some special cases in the stdlib where strings are 
    very confusing. The cgi.FieldStorage module which WSGI applications are 
    sometimes still using for form data parsing is now treating QUERY_STRING 
    as surrogate escaping, but instead of using utf-8 as charset for the URLs 
    (as browsers) it treats it as the encoding returned by 
    locale.getpreferredencoding(). I have no idea why it would do that, but 
    it's incorrect. As workaround I recommend not using cgi.FieldStorage for 
    query string parsing."
    


    这个问题的解决方法是使用sys.stdin.read来读入POST数据参数。 但是请注意,如果您的 cgi 应用程序希望读取某些内容而没有发送任何内容,则它可能会挂起。这可以通过读取 HTTP 标头中的字节数来解决:
    #!/usr/bin/env python3
    import os, sys, json
    data = sys.stdin.read(int(os.environ.get('HTTP_CONTENT_LENGTH', 0)))
    # To get data in a native python dictionary, use json.loads
    if data:
        print(list(json.loads(data).keys())) # Prints out keys of json
    
    # (You need to wrap the .keys() in list() because it would otherwise return 
    #  "dict_keys([a, b, c])" instead of [a, b, c])
    

    您可以在此处阅读有关 CGI 内部结构的更多信息:http://oreilly.com/openbook/cgi/ch04_02.html

    【讨论】:

    • 在我的情况下,我需要CONTENT_LENGTH 而不是HTTP_CONTENT_LENGTH,以防有人绊倒。 Python 3.6。
    【解决方案3】:

    接受的答案对我不起作用并且没有返回任何数据(使用 Windows Server 2012 和 Python 3.4)。

    当然,我很欣赏它可能对其他人有用,但我想发布这个以防万一它帮助任何发现我经历过的相同情况的人。

    在搜索了许多类似的问题和相关的博客文章,并自己测试了不同的方法后,对我来说获胜的组合是:

    totalBytes=int(os.environ.get('HTTP_CONTENT_LENGTH'))
    reqbin=io.open(sys.stdin.fileno(),"rb").read(totalBytes)
    

    这两行是我接收原始二进制数据(图像、音频文件等)然后转储到文件所需的全部内容。

    如果你想将接收到的数据变成一个字符串,你可以使用:

    reqstr=reqbin.decode("utf-8")
    

    最后,为了满足问题的要求,您可以使用以下方法将其解析为 JSON:

    thejson=json.loads(reqstr)
    

    我真的希望这可以帮助其他无法找到其他方法的人!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      • 2012-04-20
      • 2016-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多