将数据传递给mod_wsgi
在mod_wsgi中,我通过运行start_response()这个函数来发送页面的头部信息,但所有的页面内容都是通过yield或return来传递的。有没有办法像使用start_response()那样传递页面内容呢?使用return.yield语句在处理分块数据时限制太多了。
比如说:
def Application():
b = buffer()
[... page code ...]
while True:
out = b.flush()
if out:
yield out
class buffer:
def __init__(self):
b = ['']
l = 0
def add(self, s):
s = str(s)
l += len(s)
b.append(s)
def flush(self):
if self.l > 1000:
out = ''.join(b)
self.__init__()
return out
我希望缓冲区在页面加载时就开始输出内容,但只有在内容积累到足够多(在这个例子中是1000字节)时才输出。
3 个回答
如果你不想直接修改你的WSGI应用程序来在发送响应数据之前先进行部分缓冲,那么你可以创建一个WSGI中间件,这个中间件会把你的WSGI应用程序包裹起来,并完成这个任务。
你的应用程序是可以将数据“推送”到WSGI服务器的:
一些现有的应用框架API以不同于WSGI的方式支持无缓冲输出。具体来说,它们提供了一种“写入”功能或方法,可以写入一个无缓冲的数据块,或者提供一个带缓冲的“写入”功能和一个“刷新”机制来清空缓冲区。
不幸的是,这些API不能通过WSGI的“可迭代”应用返回值来实现,除非使用线程或其他特殊机制。
因此,为了让这些框架继续使用命令式API,WSGI包含了一个特殊的
write()
可调用对象,这个对象是由start_response
可调用对象返回的。新的WSGI应用和框架不应该使用
write()
可调用对象,如果可以避免的话。
但这并不推荐。
一般来说,应用程序通过缓冲它们(适中大小的)输出并一次性发送,能够获得最佳的吞吐量。这是在现有框架(如Zope)中常见的方法:输出会缓存在一个StringIO或类似的对象中,然后连同响应头一起一次性传输。
在WSGI中,相应的方法是应用程序简单地返回一个包含响应主体的单元素可迭代对象(比如一个列表),这个响应主体是一个单独的字符串。这是大多数应用功能的推荐方法,特别是那些生成HTML页面的功能,因为这些页面的文本通常可以轻松放入内存中。
http://www.python.org/dev/peps/pep-0333/#buffering-and-streaming
不;但我觉得这并不是限制。也许你可以贴一个示例代码,描述一下你的限制,我们可以帮你。
要处理分块数据,你只需要用 yield
来输出这些块:
def application(environ, start_response):
start_response('200 OK', [('Content-type', 'text/plain')]
yield 'Chunk 1\n'
yield 'Chunk 2\n'
yield 'Chunk 3\n'
for chunk in chunk_data_generator():
yield chunk
def chunk_data_generator()
yield 'Chunk 4\n'
yield 'Chunk 5\n'
编辑:根据你给出的评论,这里有一个在发送数据之前将其堆积到一定长度的示例:
BUFFER_SIZE = 10 # 10 bytes for testing. Use something bigger
def application(environ, start_response):
start_response('200 OK', [('Content-type', 'text/plain')]
buffer = []
size = 0
for chunk in chunk_generator():
buffer.append(chunk)
size += len(chunk)
if size > BUFFER_SIZE:
for buf in buffer:
yield buf
buffer = []
size = 0
def chunk_data_generator()
yield 'Chunk 1\n'
yield 'Chunk 2\n'
yield 'Chunk 3\n'
yield 'Chunk 4\n'
yield 'Chunk 5\n'