当我尝试在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");
}
});
}
据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
to read in POST data parameters. However please note that your cgi application can hang if it expects to read in something and nothing is sent. This is solved by reading in the number of bytes that is found in the HTTP Header:
#!/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
接受的答案对我不起作用,并且没有返回任何数据(使用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)
我真的希望这能帮助那些无法找到另一种方式的人!
很抱歉创建了新的答案,但我没有足够的声誉在您的问题下发表评论。 XD
我和你有同样的问题。我尝试了一堆解决方案,但它们没有用。然后我在@Schien回答的以下问题中找到了一个更简单的方法(非常感谢,man):
(Qazxswpoi)
对于GET:
https://stackoverflow.com/a/27893309/5392101
对于POST:
raw_data = os.getenv("QUERY_STRING")
它就像一个魅力!
在我的情况下,我raw_data = sys.stdin.read()
ed从JavaScript发送的数据,并注意到正在发送tcpdump -x -X
的Content-type
标头。所以我把它设置为text/plain
作为推荐的application/x-www-form-urlencoded
并解决了这个问题。