#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2004
    Location
    Atlantic City, NJ
    Posts
    327
    Rep Power
    13

    Inheritance Help(Again)


    Okay here is the code I have so far called mysql_class.py:

    Code:
    #!C:\Python23\python.exe
    
    import MySQLdb
    
    class Db:
        def __init__(self):
            self.host = 'localhost'
            self.user = 'user'
            self.passwd = 'password'
            self.db = 'inventory'
            self.database = MySQLdb.connect(host = self.host, user = self.user, passwd = self.passwd, db = self.db)
            self.cursor = self.database.cursor()
    
        def closeall(self):
            self.cursor.close()
            self.database.close()
    
    class Select(Db):
        def GetUsersInfoAll(self):
            self.cursor.execute("""SELECT * FROM users""")
            self.infolist = self.cursor.fetchall()
            self.closeall()
            return self.infolist
    
        def GetUsersInfoLastName(self, lname):
            self.cursor.execute("""SELECT * FROM users WHERE LastName = (%s)""", (lname))
            self.infolist = self.cursor.fetchall()
            self.closeall()
            return self.infolist
    Now from a prompt I do this:
    Code:
    >>> import mysql_class
    >>> a = mysql_class.Select()
    >>> a.GetUsersInfoAll()
    The above works fine and returns a tuple of all the information but if I try to use a. anything again it errors out:

    Code:
    >>> a.GetUsersInfoAll()
    Traceback (most recent call last):
      File "<interactive input>", line 1, in ?
      File "C:\Python23\test_class.py", line 20, in GetUsersInfoAll
        Db.cursor.execute("""SELECT * FROM users""")
      File "C:\Python23\Lib\site-packages\MySQLdb\cursors.py", line 95, in execute
        return self._execute(query, args)
      File "C:\Python23\Lib\site-packages\MySQLdb\cursors.py", line 110, in _execute
        self.errorhandler(self, TypeError, m)
    TypeError: 'NoneType' object is not callable
    I'm confused here.
    I'll learn this stuff someday.
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2004
    Location
    Atlantic City, NJ
    Posts
    327
    Rep Power
    13
    Okay I figured out the issue:

    Code:
    #!C:\Python23\python.exe
    
    import MySQLdb
    
    class Db:
        def __init__(self):
            self.host = 'MLDCOMBO1'
            self.user = 'ROOT'
            self.passwd = 'TRANSPORT'
            self.db = 'inventory'
            
        def connect(self):
            self.database = MySQLdb.connect(host = self.host, user = self.user, passwd = self.passwd, db = self.db)
            self.cursor = self.database.cursor()
    
        def closeall(self):
            self.cursor.close()
            self.database.close()
    
    class Select(Db):
        def GetUsersInfoAll(self):
            self.connect()
            self.cursor.execute("""SELECT * FROM users""")
            self.infolist = self.cursor.fetchall()
            self.closeall()
            return self.infolist
    
        def GetUsersInfoLastName(self, lname):
            self.connect()
            self.cursor.execute("""SELECT * FROM users WHERE LastName = (%s)""", (lname))
            self.infolist = self.cursor.fetchall()
            self.closeall()
            return self.infolist
    Since the connection to the database was being done in the __init__ method it was only happening once when the class was instantiated. I just created another method for it and that solved the problem.

    So now that I fixed that one I get to ask another question. I thought that since I inheritited the Db class I could do this:

    Code:
        def GetUsersInfoLastName(self, lname):
            Db.connect()
            Db.cursor.execute("""SELECT * FROM users WHERE LastName = (%s)""", (lname))
            self.infolist = Db.cursor.fetchall()
            Db.closeall()
            return self.infolist
    Apparently not since it throws all sorts of errors. I'm guessing subclasses reference superclass's methods using self because the superclass's methods actually become part of the subclass?

    Sorry for my noobish questions but I'm trying to wrap my head around all this class stuff and I'm trying to get the correct terminology down as well. Please correct me if I said anything stupid.

    Thanks.
    Last edited by Shiner_Man; May 5th, 2005 at 02:25 PM.
    I'll learn this stuff someday.
  4. #3
  5. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    You got it, if you inherit from another class it becomes part of the subclass so any attributes can be accessed via the self keyword; you're currently using Db.

    Note: this wouldn't be a problem if the methods were class methods but that's kinda pointless here, still I thought it might be worth mentioning .

    Actually, you don't been to close the connection each time. In fact this is probably a wast of resources. What I would do instead would be to initiate the connection in the __init__ method and close it manually (maybe using a close() method) or when the object is destroyed in the __del__ method.

    I've attached a smilar class which I wrote ages ago. The class is for connecting to databases using DBI compliant database modules in Python and just makes things a little simpler .

    Hope this helps,

    Mark.
    Attached Files
    programming language development: www.netytan.com Hula

  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2004
    Location
    Atlantic City, NJ
    Posts
    327
    Rep Power
    13
    Originally Posted by netytan
    You got it, if you inherit from another class it becomes part of the subclass so any attributes can be accessed via the self keyword; you're currently using Db.

    Note: this wouldn't be a problem if the methods were class methods but that's kinda pointless here, still I thought it might be worth mentioning .

    Actually, you don't been to close the connection each time. In fact this is probably a wast of resources. What I would do instead would be to initiate the connection in the __init__ method and close it manually (maybe using a close() method) or when the object is destroyed in the __del__ method.

    I've attached a smilar class which I wrote ages ago. The class is for connecting to databases using DBI compliant database modules in Python and just makes things a little simpler .

    Hope this helps,

    Mark.

    Thanks. I was looking for that DBI class you wrote.

    Anyway, I originally tried to make the connection in the __init__ method. What I found is that the connection only happens once so I have to re-instantiate the class each time I want to make a new connection.

    Am I making sense here? I'll look over your class and see what you did.

    Thanks again.

    P.S. I can't believe I actually got something somewhat working in a class.
    I'll learn this stuff someday.
  8. #5
  9. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    I suspect the reason you have to create a new instance of the class for each method call is to do with the fact that you are closing the cursor and the connection each time you call one of your query method.

    You don't need to do this so you can remove the calls to closeall(), this should help with your problem .

    Mark.
    programming language development: www.netytan.com Hula

  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2004
    Location
    Atlantic City, NJ
    Posts
    327
    Rep Power
    13

    Thumbs up


    AHA! So your saying opening the connection in __init__ and closing it in __del__ will open and close one connection every time the class is instantiated. I'm beginning to understand what your trying to convey to me. I'll check it out.

    By the way, the reason I'm so paranoid about this whole open connections thing is because I ran into a nasty bug with other psp software I was using. The connections to the MySQLdb were never getting closed and after a while mysql would just die.

    Thanks again.
    I'll learn this stuff someday.
  12. #7
  13. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    You got it. I've never heard of that bug, it is possible that whatever class you were using just didn't close the connection. I can't imagine it being a bug with MySQLdb or it would be very well known by now .

    Anyway, let me know if anything like this happens with this and I'll look further into the problem.

    Mark.
    programming language development: www.netytan.com Hula

  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2004
    Location
    Atlantic City, NJ
    Posts
    327
    Rep Power
    13
    Well, the issue was specific to mod_python. I filed a bug report for the Gentoo developers. I was able to resolve the issue myself. This is what I was talking about:

    http://www.modpython.org/FAQ/faqw.py...=faq02.024.htp
    I'll learn this stuff someday.
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2004
    Location
    Atlantic City, NJ
    Posts
    327
    Rep Power
    13
    And just to pick your brain, at what point is the __del__ method run? When is the class destructed(is that the word?)?
    Last edited by Shiner_Man; May 5th, 2005 at 10:30 PM.
    I'll learn this stuff someday.
  18. #10
  19. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    The __del__ method gets called just before the garbage collector destroys the Object however you can cause this to happen at any time by using the del keyword to force the object to be removed.

    Mark.
    programming language development: www.netytan.com Hula

  20. #11
  21. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2004
    Posts
    461
    Rep Power
    25
    Originally Posted by netytan
    The __del__ method gets called just before the garbage collector destroys the Object however you can cause this to happen at any time by using the del keyword to force the object to be removed.

    Mark.
    just to add a bit more to what netytan said, the carbage collector is ran at the end of the application so it will make sure tht the connection is closed, however if the app dies because of errors that method is never ran and the connection(well to mysql at least) stays open. So mysql will have a huge list of connections that shouldn't be there. However don't worrie about it, unless you run the buggy software 300 times in a minute or whatever mysqls limit is, you wont have a problem. Mysql will timeout those dead connections pretty well so it shouldn't case any problems.

    also does anyone know if it is ran if ctrl-c is pressed during run? Will the garbage collector still do its thing?
  22. #12
  23. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2004
    Location
    Atlantic City, NJ
    Posts
    327
    Rep Power
    13
    So it would be in my best interest to implement some sort of try/except on the connection code? I'll look into that.

    Thanks.
    I'll learn this stuff someday.
  24. #13
  25. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2005
    Posts
    78
    Rep Power
    10
    Originally Posted by CyBerHigh
    just to add a bit more to what netytan said, the carbage collector is ran at the end of the application so it will make sure tht the connection is closed, however if the app dies because of errors that method is never ran and the connection(well to mysql at least) stays open.
    You can use try/finally:
    Code:
    def run()
        try:
            main_code()
        finally:
            cleanup()
    cleanup() will run even if main_code() raises an error. (of course it's important that cleanup doesn't raise an error...)

    --OH.
  26. #14
  27. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2004
    Location
    Atlantic City, NJ
    Posts
    327
    Rep Power
    13
    hmmm...well:

    Code:
    import MySQLdb
    
    class Db:
    	def __init__(self):
    		self.db = MySQLdb.connect("shinebox", "user", "password", "jinzora2")
    		self.cursor = self.db.cursor()
    
    	def __del__(self):
    		"""Close all connections to the db.  Otherwise, mysql goes
    		poo-poo and can't handle mucho connections."""
    		self.cursor.close()
    		self.db.close()
    		
    class Select(Db):
    	def GetTables(self):
    		"""Show me what tables are in the 'jinzora2' database.  
    		It will return a tuple."""
    		try:
    			self.cursor.execute('SHOW TABLES')
    			self.infotup = self.cursor.fetchall()
    			return self.infotup
    			
    		finally:
    			self.cursor.close()
    			self.db.close()
    The statements in the finally: clause seem a bit redundant. Is there a way to call the __del__ method again or should I just create another method with the closing statements?
    I'll learn this stuff someday.

IMN logo majestic logo threadwatch logo seochat tools logo