When 'application' object being initialized - once or per request ?

56 views
Skip to first unread message

k4ml

unread,
Apr 9, 2012, 6:49:05 AM4/9/12
to modwsgi
I was toying around with simple wsgi application (I just learnt about
mod_wsgi AddHandler directive, for so long I have been using
WSGIScriptAlias to launch my wsgi app). So the idea is to have
something that closely resemble PHP way of executing the application.
Don't ask me why, just for fun. I use Django or Flask for real thing.

So here's my application defined in ../app/php.py:-


class PHPApplication(object):
def __init__(self):
self.out = []
self.counter = 0
self.counter += 1
self.out.append(str(self.counter))

def printx(self, out):
self.out.append(out)

def __call__(self, environ, start_response):
start_response('200 OK', [('Content-type', 'text/html')])
for out in self.out:
yield out


and the index.py:-


import os
import sys

CUR_DIR = os.path.abspath(os.path.dirname(__file__))
LIB_DIR = os.path.abspath(os.path.join(CUR_DIR, '../lib'))
APP_DIR = os.path.abspath(os.path.join(CUR_DIR, '../app'))

for path in (LIB_DIR, APP_DIR,):
if path not in sys.path:
sys.path.insert(0, path)

from php import PHPApplication

php = PHPApplication()
php.printx("hello world")

application = php

and the apache vhost config:-

DocumentRoot /home/kamal/pylikephp/htdocs
DirectoryIndex index.py

Options ExecCGI

AddHandler wsgi-script .py

Order allow,deny
Allow from all


WSGIDaemonProcess pylikephp processes=1 threads=2 display-name=%
{GROUP}
WSGIProcessGroup pylikephp

My initial thought was the counter will always get incremented since
the application object was created only once during mod_wsgi daemon
process initialization. But it look like the application object is
created on each requests since the counter always stayed at 1 even
after refreshing my browser few times. What I'm missing here ?

If this is how mod_wsgi work, does it safe to build my application
like this - allow user to initialized my Application, call some method
on it and be sure that the application is destroyed when the request
end ?

Joonas Lehtolahti

unread,
Apr 9, 2012, 7:03:48 AM4/9/12
to mod...@googlegroups.com
On Mon, 09 Apr 2012 13:49:05 +0300, k4ml <kamal....@gmail.com> wrote:

> class PHPApplication(object):
> def __init__(self):
> self.out = []
> self.counter = 0
> self.counter += 1
> self.out.append(str(self.counter))
>
> def printx(self, out):
> self.out.append(out)
>
> def __call__(self, environ, start_response):
> start_response('200 OK', [('Content-type', 'text/html')])
> for out in self.out:
> yield out

> from php import PHPApplication
>
> php = PHPApplication()
> php.printx("hello world")
>
> application = php
>

> But it look like the application object is
> created on each requests since the counter always stayed at 1 even
> after refreshing my browser few times. What I'm missing here ?

The only place where you do increase counter is in __init__ and you do it
only right after setting counter to 0. So counter will always be 1, no
matter what. Perhaps you should move self.counter += 1 to __call__ method?

Graham Dumpleton

unread,
Apr 9, 2012, 7:58:16 AM4/9/12
to mod...@googlegroups.com

Which will not help unless also move:

self.out = []
self.out.append(str(self.counter))

to the __call__ method.

Having:

php.printx("hello world")

at module scope is also wrong.

The basic misunderstanding here is probably the belief that the whole
contents of the file are executed on each script when they aren't.

The script is only loaded once for the life of the process and then on
each request the application callable is called. In this case the
__call__() method.

Graham

Mohd Kamal Bin Mustafa

unread,
Apr 9, 2012, 8:28:28 AM4/9/12
to mod...@googlegroups.com
On Mon, Apr 9, 2012 at 7:58 PM, Graham Dumpleton
<graham.d...@gmail.com> wrote:
> On 9 April 2012 21:03, Joonas Lehtolahti <godj...@gmail.com> wrote:
>> The only place where you do increase counter is in __init__ and you do it
>> only right after setting counter to 0. So counter will always be 1, no
>> matter what. Perhaps you should move self.counter += 1 to __call__ method?

You're right. Now the counter is incremented on each request. Thanks
for pointing out.

> Which will not help unless also move:
>
> self.out = []
> self.out.append(str(self.counter))
>
> to the __call__ method.
>
> Having:
>
> php.printx("hello world")
>
> at module scope is also wrong.
>
> The basic misunderstanding here is probably the belief that the whole
> contents of the file are executed on each script when they aren't.
>
> The script is only loaded once for the life of the process and then on
> each request the application callable is called. In this case the
> __call__() method.

Yeah, running it with AddHandler definitely has corrupted what I'd
already understand about mod_wsgi. Also realized that php.printx() is
useless since the only way to get request data is through something
that being called from __call__() method. The idea I have in mind now
is to have __call__() parse the path_info, look for something like
/index.py/page.mako in ./htdocs, process it with mako and return the
result from mako but I guess it too silly to proceed now.

Mohd Kamal Bin Mustafa

unread,
Apr 9, 2012, 8:20:12 PM4/9/12
to mod...@googlegroups.com
On Mon, Apr 9, 2012 at 8:28 PM, Mohd Kamal Bin Mustafa <ka...@smach.net> wrote:
> Yeah, running it with AddHandler definitely has corrupted what I'd
> already understand about mod_wsgi. Also realized that php.printx() is
> useless since the only way to get request data is through something
> that being called from __call__() method. The idea I have in mind now
> is to have __call__() parse the path_info, look for something like
> /index.py/page.mako in ./htdocs, process it with mako and return the
> result from mako but I guess it too silly to proceed now.

Quoting myself ... After digging through the archives I found this
post by graham [1] and spent few minutes implementing his suggestion
to use PATH_TRANSLATED to get the path to the mako template in
./htdocs and render it with mako in wsgi callable. Not that bad and
quite interesting to proceed as weekend project. Using this approach
wsgi application kind of hidden from users while mako template being
promoted to the top of the stack, backward from common approach now
with wsgi application (or framework) at the top and the template
language somewhere down the stack.

Also found another attempt to php like solution [2]. This I think
almost similar to mod_perlite attempt [3], [4]. Both however kind of
dead by now.

[1]:http://groups.google.com/group/modwsgi/msg/3c7227c232ddc08a
[2]:http://www.pyhp.org/
[3]:http://www.modperlite.org/
[4]:http://www.majordojo.com/2007/11/how-to-fix-cgi.php

Graham Dumpleton

unread,
Apr 9, 2012, 9:58:44 PM4/9/12
to mod...@googlegroups.com
You probably don't want to create a system which is wedded to how
Apache works. You would be much better off fully drinking the cool aid
as to how Python web applications work and go use a proper Python web
framework. This will save you a lot of trouble in the end.

A simple framework to get you started would be Flask (flask.pocoo.org).

Graham

> --
> You received this message because you are subscribed to the Google Groups "modwsgi" group.
> To post to this group, send email to mod...@googlegroups.com.
> To unsubscribe from this group, send email to modwsgi+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/modwsgi?hl=en.
>

Mohd Kamal Bin Mustafa

unread,
Apr 9, 2012, 10:20:56 PM4/9/12
to mod...@googlegroups.com
On Tue, Apr 10, 2012 at 9:58 AM, Graham Dumpleton
<graham.d...@gmail.com> wrote:
> You probably don't want to create a system which is wedded to how
> Apache works. You would be much better off fully drinking the cool aid
> as to how Python web applications work and go use a proper Python web
> framework. This will save you a lot of trouble in the end.
>
> A simple framework to get you started would be Flask (flask.pocoo.org).

As I said earlier, this is just for fun. I used Django and recently
Flask for real stuff ;)

This also grow from my frustration getting our new hires (a php
developer) getting up to speed with python development. We used django
at work and things that we python developers take for granted took lot
of time for them to comprehend. Most of it relate back to
understanding how python import work and also the difference between
stateless nature of PHP and long running python process. It seem easy
to us but not to them. On the import issue, it also caused by django
manipulating the path (thank god it's gone now in 1.4) it's not clear
to them what happen under the hood when running through manage.py
runserver and why django wsgi script in the documentation doesn't work
and they have to fix it to add path to their lib into sys.path. In the
end, they simply ask why so much trouble ?

Graham Dumpleton

unread,
Apr 9, 2012, 10:32:07 PM4/9/12
to mod...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages