views:

197

answers:

2

Hello, here is a simple threading program which works fine:

import psycopg2
import threading
import time

class testit(threading.Thread):
    def __init__(self, currency):
        threading.Thread.__init__(self)
        self.currency = currency

    def run(self):
        global SQLConnection
        global cursor
        SQLString = "Select dval from ddata where dname ='%s' and ddate = '2009-07-17'" \
                %self.currency
        z = time.time()
        while (time.time() - z) < 2:
            print SQLString

SQLConnection = psycopg2.connect(database = "db", user = "xxxx", password = "xxxx")
cursor = SQLConnection.cursor()

a = testit('EURCZK')
b = testit('EURPLN')
a.start()
b.start()

However as soon as I try to start accessing the postgresql database in the thread with the following code, I always get a stop-sign crash:

import psycopg2
import threading
import time

class testit(threading.Thread):
    def __init__(self, currency):
        threading.Thread.__init__(self)
        self.currency = currency

    def run(self):
        global SQLConnection
        global cursor
        SQLString = "Select dval from ddata where dname ='%s'and ddate = '2009-07-17'" %self.currency
        z = time.time()
        while (time.time() - z) < 2:
            cursor.execute(SQLString)
            print cursor.fetchall()

SQLConnection = psycopg2.connect(database = "db", user = "xxxx", password = "xxxx")
cursor = SQLConnection.cursor()

a = testit('EURCZK')
b = testit('EURPLN')
a.start()
b.start()

The only difference between the two is in the while loop. I am fairly new to thread programming. Is the postgres library (psycopg2) not "thread safe"? All this is running on Windows XP. Anything I can do?

Thanks.

+1  A: 
global SQLConnection
global cursor

Seems you're accessing globals from multiple threads ? You should never do that unless those globals are thread safe, or you provide the proper locking yourself.

You now have 2 threads accessing the same connection and the same cursor. They'll step on eachothers toes. psycopg2 connection might be thread safe but cursors are not.

Use one cursor(probably one connection as well) per thread.

nos
gotcha nos. While you were answering I figured the error of my ways. See my own answer. Thanks very much.
Thomas Browne
A: 

bingo it's working. Someone left an answer but then seems to have removed it, to give each thread its own connection. And yep that solves it. So this code works:

import psycopg2
import threading
import time

class testit(threading.Thread):
    def __init__(self, currency):
        threading.Thread.__init__(self)
        self.currency = currency 
        self.SQLConnection = psycopg2.connect(database = "db", user = "xxxx", password = "xxxx")
        self.cursor = self.SQLConnection.cursor()

    def run(self):
        SQLString = "Select dval from ddata where dname ='%s' and ddate = '2009-07-17'" \
                %self.currency
        z = time.time()
        while (time.time() - z) < 2:
            self.cursor.execute(SQLString)
            print self.cursor.fetchall()

a = testit('EURCZK')
b = testit('EURPLN')
a.start()
b.start()
Thomas Browne
I left the original answer, but I deleted when I read in psycopg's docs that you should have been able to do what you were trying to do. :-)
Christopher
There's not need to protect the connection. See the value of `psycopg2.threadsafety`, and what it means [here](http://www.python.org/dev/peps/pep-0249/).
Bastien Léonard
This example: http://initd.org/svn/psycopg/psycopg2/trunk/examples/threads.py also indicates that you should be able to do what you were trying. Anyway, you might want to try using a connection pool even if you can't do one connection for all threads.
Christopher
thanks Christopher.
Thomas Browne