In short, I don't understand that what happens it CherryPy GETs two requeste to same resource at the same time, are variables mixed or what is happening ?
I have this problem, I am trying to create a very basic web service with Python 2.7 and CherryPy 3.2.2.
Web service is consumed by front end which makes ajax requests to web service with jquery/ajax.
Now, I have created a CherryPy program and I am using its builtin wsgi server. I have CherryPy configuration like this:
conf = {
'global': {
'server.socket_host': '127.0.0.1',
'server.socket_port': 8000,
},
'/': {
'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
}
}
cherrypy.quickstart(root, '/', conf)
And then I have:
root.customers = getCustomers()
And the actual class for this:
class getCustomers(object):
def __init__(self):
pass
exposed = True
def GET(self,callback,**kwargs):
self.callback = callback
self.cnxn= pyodbc.connect(constr)
self.cursor = self.cnxn.cursor()
cherrypy.response.headers['Content-Type']='application/json'
self.cursor.execute("""select * from customers
""", self.job_worknumber)
self.customers = self.cursor.fetchall()
self.objects_list = []
for c in self.customers
r = collections.OrderedDict()
r['customer_id'] = c.customer_id
r['customer_name'] = c.customer_name
self.objects_list.append(r)
self.cursor.close()
self.cnxn.close()
self.w = collections.OrderedDict()
self.w['data1'] = self.objects_list
#w['errors'] = 'error'
self.j = json.dumps(self.w)
#cursor2.close()
return self.callback+'('+self.j+');'
Now when I create a GET request to that I get what I want, but if I create web page which sends two GET request to web service at page load the second request will almost always fail with an error like:
ProgrammingError: Attempt to use a closed cursor.
Or other times:
ProgrammingError: No results. Previous SQL was not a query
So what is happening, are my requests sharing same variables it they are run at the very same time ? Can I configure CherryPy to only serve one request at a time ?
As @DanielRoseman noticed you should not set variables on self
. You have create only one instance of getCustomers
class so CherryPy will call GET
method on the same instance from multiple threads (there's a thread pool which handles requests). Therfore using
self.cursor = self.cnxn.cursor()
is not thread-safe and you end up with different cursor in
self.cursor.execute("""select * from customers
""", self.job_worknumber)
or self.cursor.fetchall()
or in any other place (it is a bit random).
However changing all variables to local (don't use self
at all in GET
) should fix the problem.