Python CGI脚本在uWSGI尝试读取sys.stdin时挂起

时间:2015-04-13 19:48:40

标签: python json nginx uwsgi

我试图简单地读取传递给python cgi脚本的json数据,但是当我调用sys.stdin时它会挂起。我用--hourour-stdin开始使用uWSGI并没有任何区别。我使用的是nginx - >带有cgi插件的uWSGI。

data = json.load(sys.stdin)
print "Status: 200 OK"
print "Content-Type: application/json"
print "Length:", len(data)
print ""
print data

编辑:如果我限制它读取的字符数,它就不会挂起。所以它等待EOF。我缺少一些uWSGI设置吗?

2 个答案:

答案 0 :(得分:1)

您可以使用os.environ['CONTENT_LENGTH']环境变量来读取确切的字节数,作为stdin未被CGI lib终止的解决方法。

import os

if not os.environ['CONTENT_LENGTH']:
    data = {}
else:
    post_length = int(os.environ['CONTENT_LENGTH'])
    # post_length stores byte count, but stdin.read, apparently, takes the character count
    post_string = sys.stdin.buffer.read(post_length).decode('utf-8')
    data = json.loads(post_string)

假设您的文字以utf-8编码。

答案 1 :(得分:0)

让我先从一些背景开始。

这是一个description of the CGI protocol。页面上的两个亮点:

  1. 传统的CGI将为每个请求分别调用perl / python / ...解释器。
  2. FastCGI使解释器保持活力:
  3.   

    FastCGI允许单个长时间运行的进程处理多个用户请求,同时保持接近CGI编程模型,保留简单性,同时消除为每个请求创建新进程的开销。

    您的问题是:每次请求后stdin都没有终止(EOF)。保持链接打开实际上是一个好主意。此外,前面的HTTP连接也可能是 keepalive

    我从this page学到了一种通过fastCGI per-request环境变量检查请求结束的方法。它们可以通过os.environ

    获得
    # read until EOF set in environment
    while not os.environ.get("stdin_eof", True):
        buf += sys.stdin.read(1)
    

    另一个想法可能是使用增量JSON解析器,如ijson