[Web-SIG] WSGI and start_response

P.J. Eby pje at telecommunity.com
Thu Apr 8 21:09:39 CEST 2010


At 08:06 PM 4/8/2010 +0200, Manlio Perillo wrote:
>What I'm trying to do is:
>
>* as in the example I posted, turn Mako render function in a generator.
>
>   The reason is that I would lite to to implement support for Nginx
>   subrequests.

By subrequest, do you mean that one request is invoking another, like 
one WSGI application calling multiple other WSGI applications to 
render one page containing contents from more than one?


>   During a subrequest, the generated response body is sent directly to
>   the client, so it is necessary to be able to flush the Mako buffer

I don't quite understand this, since I don't know what Mako is, or, 
if it's a template engine, what flushing its buffer would have to do 
with WSGI buffering.


> > Under
> > WSGI 1, you can do this by yielding empty strings before calling
> > start_response.
>
>No, in this case this is not what I need to do.

Well, if that's not when you're needing to suspend the application, 
then I don't see what you're losing in WSGI 2.


>I need to call start_response, since the greenlet middleware will yield
>data to the caller before the application returns.

I still don't understand you.  In WSGI 1, the only way to suspend 
execution (without using greenlets) prior to determining the headers 
is to yield empty strings.

I'm beginning to wonder if maybe what you're saying is that you want 
to be able to write an application function in the form of a 
generator?  If so, be aware that any WSGI 1 app written as:

      def app(environ, start_response):
          start_response(status, headers)
          yield "foo"
          yield "bar"

can be written as a WSGI 2 app thus:

      def app(environ, start_response):
          def respond():
              yield "foo"
              yield "bar"
          return status, headers, respond()

This is also a good time for people to learn that generators are 
usually a *very bad* way to write WSGI apps - yielding is for server 
push or sending blocks of large files, not tiny strings.  In general, 
if you're yielding more than one block, you're almost certainly doing 
WSGI wrong.  The typical HTML, XML, or JSON output that's 99% of a 
webapp's requests should be transmitted as a single string, rather 
than as a series of snippets.

IOW, the absence of generator support in WSGI 2 is a feature, not a bug.


>In my new attempt I plan to:
>
>1) Implement the simple suspend/resume extension
>2) Implement a Python extension module that wraps the Nginx events
>    system.
>3) Implement a pure Python WSGI middleware that, using greenlets, will
>    enable normal applications to take advantage of Nginx async features.

I think maybe I'm understanding a little better now -- you want to 
implement the WSGI gateway entirely in C, without using any Python, 
and without using the greenlet API directly.

I think I've been unable to understand because I'm thinking in terms 
of a server implemented in Python, or at least that has the WSGI part 
implemented in Python.


>Do you think it will possible to implement all the requirements of WSGI
>2 (including Python 3.x support) in a simple adapter on top of WSGI 1.0 ?

My practical experience with Python 3 is essentially nonexistent, but 
being able to implement WSGI 2 in terms of WSGI 1 is a *design 
requirement* for WSGI 2; it's likely that much early use and 
development of WSGI 2 will be done through such an adapter.


>And what about applications that need to use the WSGI 1.0 API but
>require to run with Python 3.x?

That's a tougher nut to crack; again, my practical experience with 
Python 3 is essentially nonexistent.



More information about the Web-SIG mailing list