1

When I was trying to execute a query -

select * from students where id = 20

using Python's MySQLdb library, I was getting an exception: _mysql_exceptions.OperationalError saying MySQL server has gone away. Some of my friends suggested me to use the existing mysql connection. So I started referring this link and used the same Singleton class from the link in my code below, it still gives me the same exception.

#DBConnect.py
import MySQLdb as connector
from Singleton import Singleton
class DBConnect:
    # As the link suggests
    __metaclass__  = Singleton
    def __init__(self):
        self.dbConnection = connector.Connect(host = 'localhost', user = 'root', 
                                          passwd = 'root', db = 'school')
        self.dbCursor = self.dbConnection.cursor(cursorclass=connector.cursors.DictCursor) 

    def getRecord(self,query):
        self.dbCursor.execute(query)
        result = self.dbCursor.fetchone()
        return result

    def __del__(self):
        self.dbCursor.close()
        self.dbConnection.close()

if __name__ == '__main__':
    dc = DBConnect()
    query = "select * from students where id = 20"
    result = dc.getRecord(query)

I have tried to create more instances of DBConnect like -

dc2 = DBConnect()
dc3 = DBConnect()

When I print dc, dc2 and dc3 it gives -

<__main__.DBConnect object at 0x8a5fe8c> 
<__main__.DBConnect object at 0x8a5fe8c> 
<__main__.DBConnect object at 0x8a5fe8c>

Meaning the same instance. So what seems to be the problem? Why can't I resolve this?

Hussain
  • 5,057
  • 6
  • 45
  • 71

1 Answers1

1

The problem is actually the Singleton. Its sole purpose as a singleton is to ensure that only one instance of a class is created. When you use the __metaclass__ = Singleton line in your class, you are ensuring that only one instance of DBConnect can be created, and that any subsequent instantiations of that class will point back to the same instance. Therefore when you use dc2 = DBConnect() and dc3 = DBConnect(), you are just referring back to the same instance, hence the same identifier you see.

Here is the part of your Singleton code that is causing the behavior:

def __call__(self, *args, **kw):
        if self.instance is None:
            self.instance = super(Singleton, self).__call__(*args, **kw)

        return self.instance

After you create an instance of DBConnect, self.instance is no longer None, meaning that the instance you first created (which gets stored in self.instance) is the one that is returned anytime you call your class.

My (unsolicited) advice would be to start from scratch and just try to get a basic connection working with the MySQLdb library - the error you mention up top is indicative of MySQL error, so doing some troubleshooting there may be the best course of action.

RocketDonkey
  • 36,383
  • 7
  • 80
  • 84
  • So my problem is not related to singleton? – Hussain Nov 22 '12 at 09:07
  • @HussainTamboli Right - the initial problem sounds like it is simply not making a connection to MySQL itself. Have you tried re-attempting the connection in the same script? – RocketDonkey Nov 22 '12 at 09:14
  • Yes. I have been running the DBConnect.py script again and again. so my "__init__" is creating a new connection. – Hussain Nov 22 '12 at 09:32
  • @Sorry, I meant retrying it without the singleton - just a very basic connector. See http://stackoverflow.com/questions/567622/is-there-a-pythonic-way-to-try-something-up-to-a-maximum-number-of-times answer for a potential implementation. – RocketDonkey Nov 22 '12 at 09:41
  • 1
    @HussainTamboli That last comment was for you (and I think that means it's bedtime for me :) ) – RocketDonkey Nov 22 '12 at 10:03
  • +1. Good link. but these are just the attempts to connect to the mysql server. How can I get a reliable connection each time I do _getRecord_ . How do I resolve the problem of "mysql has gone away"? – Hussain Nov 22 '12 at 10:24
  • @HussainTamboli I'll do some more thinking tomorrow, but this http://dev.mysql.com/doc/refman/5.0/en/gone-away.html is the MySQL documentation on the actual error and its causes. It seems that this can be related to a client not having proper permissions (usually that is a different error, but I don't recall the special case in this situation), having certain values for connection variables, or oftentimes it can be that the connection just went idle (connection.ping() was a suggestion there). – RocketDonkey Nov 22 '12 at 10:50
  • @HussainTamboli I would suggest creating a fresh script and seeing if you can establish a connection with a very basic setup (I.e. straight from the docs). If not, there is likely something going on with the MySQL host. – RocketDonkey Nov 22 '12 at 10:51