In daemon mode, with threads=1 :
def application(environ, start_response):
status = '200 OK'
output = "con= %s" % cgi.escape(repr(pool.connection()))
loc = threading.local()
try:
loc.i += 1
except AttributeError:
loc.i = 0
output = 'i=%s' % loc.i
response_headers = [('Content-type', 'text/html'), ]
start_response(status, response_headers)
return [output]
threading.local doesn't stay between requests. Is it normal ?
I found this with DBUtils wich doesn't reuse connection.
I missed something ?
--
William Dodé - http://flibuste.net
Informaticien Indépendant
If you want something to persist between requests, just make it a
global variable within the file, you do not need to use
threading.local(). Depending on type of data, global declaration may
be needed in function scope so that on assignment it doesn't just
create a local variable to function (which is what is happening now).
In doing this, if a multithreaded application you would however need
to protect using thread mutex locks any updates to the global data.
This is presuming all threads should share the global data. If each
thread should have its own, then threading.local() may be okay, but
you need to initialise it once outside of the function, actually at
global scope, not like what you are doing now.
BTW, also be careful of embedded mode as source code reloading could
cause issues in that case. See:
http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode
Graham
I thought it's a singleton...
But even if i put it outside the function it doesn't show what i expect
:
import cgi
import threading
loc = threading.local()
def application(environ, start_response):
status = '200 OK'
try:
loc.i += 1
except AttributeError:
loc.i = 0
output = '%s i=%s' % (loc, loc.i)
response_headers = [('Content-type', 'text/html'), ]
start_response(status, response_headers)
return [cgi.escape(output)]
The output is everytime <thread._local object at 0xb710d6e0> i=0
>
> In doing this, if a multithreaded application you would however need
> to protect using thread mutex locks any updates to the global data.
> This is presuming all threads should share the global data. If each
> thread should have its own, then threading.local() may be okay, but
> you need to initialise it once outside of the function, actually at
> global scope, not like what you are doing now.
It seems that DBUtils.PersistentDB use threading.local() to keep one
connection for each thread. I cannot make it work with mod_wsgi...
>
> BTW, also be careful of embedded mode as source code reloading could
> cause issues in that case. See:
>
> http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode
I use only deamon mode
thx
#!/usr/bin/python
import cgi
import threading
import sys
import os
class MyLoc(threading.local):
def __init__(self):
print >> sys.stderr , 'init'
myloc = MyLoc()
def application(environ, start_response):
status = '200 OK'
myloc.i = 0
print >> sys.stderr, 'pid: %s id: %s id.__dict__: %s' % (os.getpid(), id(myloc), id(myloc.__dict__))
output = ''
response_headers = [('Content-type', 'text/html'), ]
start_response(status, response_headers)
return [cgi.escape(output)]
[Fri Oct 03 11:37:04 2008] [error] init
[Fri Oct 03 11:37:04 2008] [error] pid: 1836 id: 3067827220 id.__dict__: 3067884244
[Fri Oct 03 11:37:04 2008] [error] init
[Fri Oct 03 11:37:04 2008] [error] pid: 1836 id: 3067827220 id.__dict__: 3067885740
[Fri Oct 03 11:37:05 2008] [error] init
[Fri Oct 03 11:37:05 2008] [error] pid: 1836 id: 3067827220 id.__dict__: 3067884244
[Fri Oct 03 11:37:05 2008] [error] init
[Fri Oct 03 11:37:05 2008] [error] pid: 1836 id: 3067827220 id.__dict__: 3067885740
init should not be called and __dict__ should not be different
The same with wsgiref :
from wsgiref.simple_server import make_server
make_server('',8080,application).serve_forever()
init
pid: 1868 id: 3082036284 id.__dict__: 3082022260
pid: 1868 id: 3082036284 id.__dict__: 3082022260
pid: 1868 id: 3082036284 id.__dict__: 3082022260
pid: 1868 id: 3082036284 id.__dict__: 3082022260
pid: 1868 id: 3082036284 id.__dict__: 3082022260
I'll look if i can reproduce this with the code of _threading_local
With _threading_local it works (python implementation)
import _threading_local
class MyLoc(_threading_local.local):
[Fri Oct 03 11:47:08 2008] [error] init
[Fri Oct 03 11:47:08 2008] [error] pid: 2091 id: 3067888900 id.__dict__: 3067885876
[Fri Oct 03 11:47:08 2008] [error] pid: 2091 id: 3067888900 id.__dict__: 3067885876
[Fri Oct 03 11:47:09 2008] [error] pid: 2091 id: 3067888900 id.__dict__: 3067885876
The threading.local() dictionary is specific to a thread within an interpreter.
As already explained though, because of how mod_wsgi is currently
implemented, this behaviour, ie., what you would see for command line
Python, only applies if forcing application to run in main
interpreter. That is, when have:
WSGIApplicationGroup %{GLOBAL}
Graham
At a guess, something like:
import threading
local = threading.local()
def application(.....):
try:
db = local.db
except:
db = local.db = <stuff to create connection>
db.execute("SELECT documentation FROM manual",())
Graham
# Global !!!!!!!
local = threading.local()
def application(environ, start_response):
try:
db = local.db
except:
local.db = _mysql.connect('127.0.0.1','root','root','www')
db = local.db
Graham
2008/10/6 gert <gert.c...@gmail.com>:
Graham
2008/10/6 Graham Dumpleton <graham.d...@gmail.com>:
No one will never know because you never post enough information. If
the script is generating a 500 error response, what was the traceback
or other error in the Apache error log? Have you tried to debug what
was causing the error?
Graham
More or less, it give me alternatively two differents local instances...
But i'm agree with your analyze, that to use threading.local is not
reliable. It's ok to keep the connection for the time of the request but
not for a persistent pool between requests. It's just to know about it.
The only problem is that there is not a lot of db pool utilities and
dbutils is one of the most famous...
You have an InterfaceError, then, look also at the log of your database
server...
Did you loose the connection ? Did you share a not thread safe
connection ?
...
> The only problem is that there is not a lot of db pool utilities and
> dbutils is one of the most famous...
>
I reported the problem on the dbutils list
Which says absolutely nothing.
Just because I suggested to someone else that gdb could be used to
debug an issue, doesn't mean it is then a magic bullet that is
applicable to every situation. It will only be of use it quite
specific situations.
I sincerely hope that the debug suggestions you give to people will
not now expand to, 'replace your whole Apache configuration with
yours' and 'run gdb to work out problem'. Both suggestions aren't
helpful. :-)
Graham
It is. In your example db will be shared between requests.
But if you have more than one thread you have to know how to share
theses resources ! Is your connection thread safe ?
Don't forget also that if you share the same db connection between
request you cannot use transaction...
You use _mysql instead of mysql and a query on the connection instead of
the cursor... I don't know what you do !
the apache virtualhost conf :
WSGIDaemonProcess blakie.riol user=wilk group=www-user stack-size=524288 python-path=/home/web/wilk/pynclude:/home/web/wilk/blakie.riol/pynclude home=/home/web/wilk threads=1 inactivity-timeout=300 display-name=wsgi-blakie.riol
WSGIProcessGroup blakie.riol
WSGIApplicationGroup %{GLOBAL}
AddHandler wsgi-script .wsgi
the output :
[Wed Oct 08 12:52:47 2008] [error] -- start --
[Wed Oct 08 12:52:47 2008] [error] blakie.riol
[Wed Oct 08 12:52:47 2008] [error]
[Wed Oct 08 12:52:47 2008] [error] False
[Wed Oct 08 12:52:47 2008] [error] False
[Wed Oct 08 12:52:47 2008] [error] <_MainThread(MainThread, started)>
[Wed Oct 08 12:52:47 2008] [error] pid: 12864 id: 3072714848 id.__dict__: 3070588148
[Wed Oct 08 12:52:47 2008] [error] -- start --
[Wed Oct 08 12:52:47 2008] [error] blakie.riol
[Wed Oct 08 12:52:47 2008] [error]
[Wed Oct 08 12:52:47 2008] [error] False
[Wed Oct 08 12:52:47 2008] [error] False
[Wed Oct 08 12:52:47 2008] [error] <_MainThread(MainThread, started)>
[Wed Oct 08 12:52:47 2008] [error] pid: 12864 id: 3072714848 id.__dict__: 3070589644
[Wed Oct 08 12:52:47 2008] [error] -- start --
[Wed Oct 08 12:52:47 2008] [error] blakie.riol
[Wed Oct 08 12:52:47 2008] [error]
[Wed Oct 08 12:52:47 2008] [error] False
[Wed Oct 08 12:52:47 2008] [error] False
[Wed Oct 08 12:52:47 2008] [error] <_MainThread(MainThread, started)>
[Wed Oct 08 12:52:47 2008] [error] pid: 12864 id: 3072714848 id.__dict__: 3070588148
[Wed Oct 08 12:52:47 2008] [error] -- start --
[Wed Oct 08 12:52:47 2008] [error] blakie.riol
[Wed Oct 08 12:52:47 2008] [error]
[Wed Oct 08 12:52:47 2008] [error] False
[Wed Oct 08 12:52:47 2008] [error] False
[Wed Oct 08 12:52:47 2008] [error] <_MainThread(MainThread, started)>
[Wed Oct 08 12:52:47 2008] [error] pid: 12864 id: 3072714848 id.__dict__: 3070589644
[Wed Oct 08 12:53:04 2008] [error] -- start --
[Wed Oct 08 12:53:04 2008] [error] blakie.riol
[Wed Oct 08 12:53:04 2008] [error]
[Wed Oct 08 12:53:04 2008] [error] False
[Wed Oct 08 12:53:04 2008] [error] False
[Wed Oct 08 12:53:04 2008] [error] <_MainThread(MainThread, started)>
[Wed Oct 08 12:53:04 2008] [error] pid: 12864 id: 3072714848 id.__dict__: 3070588148
[Wed Oct 08 12:53:05 2008] [error] -- start --
[Wed Oct 08 12:53:05 2008] [error] blakie.riol
[Wed Oct 08 12:53:05 2008] [error]
[Wed Oct 08 12:53:05 2008] [error] False
[Wed Oct 08 12:53:05 2008] [error] False
[Wed Oct 08 12:53:05 2008] [error] <_MainThread(MainThread, started)>
[Wed Oct 08 12:53:05 2008] [error] pid: 12864 id: 3072714848 id.__dict__: 3070589644
#!/usr/bin/python
import cgi
import threading
import sys
import os
import threading
myloc = threading.local()
def application(environ, start_response):
status = '200 OK'
print >> sys.stderr, '-- start --'
print >> sys.stderr, environ.get('mod_wsgi.process_group')
print >> sys.stderr, environ.get('mod_wsgi.application_group')
print >> sys.stderr, environ.get('wsgi.multithread')
print >> sys.stderr, environ.get('wsgi.multiprocess')
print >> sys.stderr, threading.currentThread()
ch = 'pid: %s id: %s id.__dict__: %s' % (os.getpid(), id(myloc), id(myloc.__dict__))
print >> sys.stderr, ch
output = ch
response_headers = [('Content-type', 'text/html'), ]
start_response(status, response_headers)
return [cgi.escape(output)]
DBUtils 1.0rc1 now works with mod_wsgi :-)