Python MySQL自定义重连类未保持服务器连接开放

1 投票
1 回答
2292 浏览
提问于 2025-04-17 09:10

我有一个用Python写的自定义类,用来重新建立MySQL的连接,如果当前的连接断了。问题是,当前的连接总是看起来是断开的,总是进入我代码中的异常处理部分。

class DB:
    conn = None
    def connect( self ):
            try:
               self.conn = MySQLdb.connect("localhost", "xxxx", "xxxxxx", "Systems")
            except ( AttributeError, Mysqldb.OperationalError ), e:
               raise e

    def query( self, sql, params ):
            try:
               cursor = self.conn.cursor()
               cursor.execute( sql, ( params ) )
            except ( AttributeError, MySQLdb.OperationalError ), e:
               print 'exception generated during sql connection: ', e
               self.connect()
               cursor = self.conn.cursor()
               cursor.execute( sql, ( params ) )
            cursor.close()
            return cursor

    def close( self ):
            try:
               if self.conn:
                  self.conn.close()
                  print '...Closed Database Connection: ' + self.conn
               else:
                  print '...No Database Connection to Close.'
            except ( AttributeError, MySQLdb.OperationalError ), e:
               raise e

db = DB()
db.query( sql, myParams )

问题有两个方面。1) 当我调用 db.close() 时,输出显示 ...没有数据库连接。2) 每次我执行 db.query( sql, myParams ) 时,它都会进入异常处理部分,并输出 在SQL连接期间生成的异常:

看起来我的数据库连接在每次查询调用后都自己关闭了。但我不知道为什么会这样。对此问题的任何帮助都将非常感激。

1 个回答

2
  • 第一次调用 db.query 时,self.conn 是空的(None)。所以,确实你会在第一次调用 db.query 时看到一个关于“sql连接时产生异常”的错误信息。不过,之后再调用 db.query 就不会出现这个信息了。

    如果你加上

    def __init__(self):
        self.connect()
    

    那么在你创建 db = DB() 的时候,self.conn 就会被初始化。这样你就不会看到错误信息了。或者,如果你只想在需要的时候才建立连接,那就直接去掉错误信息的提示。

  • 你可以把 conn = None 从 DB 类中去掉。代码仍然可以正常工作,基本上是一样的,只是在 self.conn 没有设置时会抛出一个 AttributeError 的错误。

  • 另外要注意,如果你的 sql 是一个 SELECT 语句,你就不应该在 DB.query 中调用 cursor.close(),因为之后再调用 cursor.fetchall() 就会失效。


这里有一些示例代码,展示了在上面提到的修改后,exception generated during sql connection 信息只会打印一次,而 db.close() 会正确打印出 ...Closed Database Connection:

如果你的代码表现得不一样,请修改下面的代码来演示这种行为。

import MySQLdb
import config

class DB:
    def connect(self):
        try:
            self.conn = MySQLdb.connect("localhost",
                                        config.USER, config.PASS, config.MYDB)
        except (AttributeError, MySQLdb.OperationalError), e:
            raise e

    def query(self, sql, params = ()):
        try:
            cursor = self.conn.cursor()
            cursor.execute(sql, params)
        except (AttributeError, MySQLdb.OperationalError) as e:
            print 'exception generated during sql connection: ', e
            self.connect()
            cursor = self.conn.cursor()
            cursor.execute(sql, params)
        return cursor

    def close(self):
        try:
            if self.conn:
                self.conn.close()
                print '...Closed Database Connection: ' + str(self.conn)
            else:
                print '...No Database Connection to Close.'
        except (AttributeError, MySQLdb.OperationalError) as e:
            raise e

db = DB()
sql = '''DROP TABLE IF EXISTS foo'''
db.query(sql)

sql = '''CREATE TABLE foo (bar INT(11))'''
db.query(sql)

db.close()

# exception generated during sql connection:  DB instance has no attribute 'conn'
# ...Closed Database Connection: <_mysql.connection closed at 8769f8c>

config.py:

USER = 'myusername'
PASS = 'mypasswd'
HOST = 'localhost'
MYDB = 'dbname'

撰写回答