[Web-SIG] A Python Web Application Package and Format

Graham Dumpleton graham.dumpleton at gmail.com
Thu Apr 14 09:53:09 CEST 2011


On 14 April 2011 16:57, Alice Bevan–McGregor <alice at gothcandy.com> wrote:
>> 3. Define how to get the WSGI app.  This is WSGI specific, but (1) is
>> *not* WSGI specific (it's only Python specific, and would apply well to
>> other platforms)
>
> I could imagine there would be multiple "application types":
>
> :: WSGI application.  Define a package dot-notation entry point to a WSGI
> application factory.

Why can't it be a path to a WSGI script file. This actually works more
universally as it works for servers which map URLs to file based
resources as well. Also allows alternate extensions than .py and also
allows basename of file name to be arbitrarily named, both of which
help with those same servers which map URLs to file base resources. It
also allows same name WSGI script file to exist in multiple locations
managed by same server without having to create an overarching package
structure with __init__.py files everywhere.

For WSGI servers which currently require a dotted path, eg gunicorn:

  gunicorn myapp

Then it changes to also allow:

  gunicorn --script myapp.wsgi

The server just has to construct a new Python module with a __name__
which relates to the absolute file system path and exec code within
that context to create the module itself. Nothing too difficult.

Because the WSGI script file is identified by explicit filesystem
path, you don't have to worry about what current working directory is
or otherwise set sys.path to allow it to be imported initially. The
WSGI script file then can itself even be responsible for further setup
of sys.path as appropriate and so be more self contained and not
dependent on an external launch system.

I have also always seen it as a PITA that for various of the WSGI
servers you always had to do:

  python myapp.py

and in the end of myapp.py add bolier plate like:

  from wsgiref.simple_server import make_server

  httpd = make_server('', 8000, application)
  print "Serving on port 8000..."
  httpd.serve_forever()

Use a different server which required such boilerplate and you had to change it.

Even where WSGI servers allowed you to specific a Python module as
command line argument, options all differed and you also needed to
know where WSGI server was installed to run it.

Using a WSGI script file as the lowest common denominator, it would
also be nice to be able to do something like:

  python -m gunicorn.server myapp.wsgi
  python -m wsgiref.server myapp.wsgi

Ie., use the '-m' option for Python command line to have the installed
module act as the processor for the WSGI script file, thereby avoiding
the need to modify the script. This lowest common denominator option
could handle a few common options which all servers would need to
accept such as listener host, port and perhaps even concepts of
processes/threads.

If you really wanted to tie the script to a particular method, but
still make it easy to use something else instead, then do it with a #!
line.

  #!/usr/bin/env python -m gunicorn -- --host localhost --port 8000

with the rest of the file being the normal WSGI script file contents,
without any special __main__ section as that is handled by the #!
line.

FWIW, I did bring this up a couple of years back, but then there was
little interest back then in trying to standardise deployment setup so
there was some measure of commonality between WSGI servers.

Graham


More information about the Web-SIG mailing list