如何在不使用CGI的情况下在python3.x中获取POST“data”变量?

时间:2014-07-08 17:48:19

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

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

[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");
       }
    });
}

4 个答案:

答案 0 :(得分:4)

根据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

答案 1 :(得分:1)

接受的答案对我没有用,也没有返回任何数据(使用Windows Server 2012和Python 3.4)。

当然我很欣赏它可能对其他人有用,但是想发布这个以防万一找到我遇到的相同情况的人。

拖网许多类似的问题后&amp;相关的博客文章,以及我自己测试不同的方法,对我而言的获胜组合是:

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)

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

答案 2 :(得分:1)

很抱歉创建了新的答案,但我没有足够的声誉来根据您的问题发表评论。 XD

我和你有同样的问题。我尝试了一堆解决方案,但他们没有工作。然后我在@Schien回答的以下问题中找到了一个更简单的方法(非常感谢,伙计):

https://stackoverflow.com/a/27893309/5392101

获取GET:

raw_data = os.getenv("QUERY_STRING")

用于POST:

raw_data = sys.stdin.read()

它就像一个魅力!

答案 3 :(得分:0)

在我的情况下,我tcpdump -x -X整理了从JavaScript发送的数据,并注意到Content-type的{​​{1}}标头正在发送。因此我按照推荐的here将其设置为text/plain,并解决了该问题。