如何在Python中仅初始化一次数据库连接并在运行时重用它?

M Λ*_*I K 8 python database class

我目前正在开发一个巨大的项目,该项目不断执行查询。我的问题是,我的旧代码总是创建一个新的数据库连接和游标,这极大地降低了速度。所以我认为是时候创建一个新的数据库类了,目前看起来像这样:

class Database(object):

   _instance = None

   def __new__(cls):
      if cls._instance is None:
         cls._instance = object.__new__(cls)
         try:
            connection = Database._instance.connection = mysql.connector.connect(host="127.0.0.1", user="root", password="", database="db_test")
            cursor = Database._instance.cursor = connection.cursor()
         except Exception as error:
            print("Error: Connection not established {}".format(error))
         else:
            print("Connection established")
      return cls._instance
    
   def __init__(self):
      self.connection = self._instance.connection
      self.cursor = self._instance.cursor
   
   # Do database stuff here
Run Code Online (Sandbox Code Playgroud)

查询将使用该类,如下所示:

def foo():
   with Database() as cursor:
      cursor.execute("STATEMENT")
Run Code Online (Sandbox Code Playgroud)

我不确定,无论创建该类的频率如何,这是否仅创建一次连接。也许有人知道如何仅初始化一次连接以及如何在之后的类中使用它,或者可能知道我的解决方案是否正确。我很感谢任何帮助!

M Λ*_*I K 16

解释

这里的关键字显然是类变量。查看官方文档,我们可以看到,除了实例变量之外,类变量是由所有类实例共享的,无论存在多少个类实例。

一般来说,实例变量用于每个实例唯一的数据,类变量用于类的所有实例共享的属性和方法:

因此,让我们假设您有该类的多个实例。类本身的定义如下。

class Dog:
   
   kind = "canine"          # class variable shared by all instances

   def __init__(self, name):
      self.name = name      # instance variable unique to each instance
Run Code Online (Sandbox Code Playgroud)

为了更好地理解类变量和实例变量之间的区别,我想在这里举一个小例子:

>>> d = Dog("Fido")
>>> e = Dog("Buddy")
>>> d.kind   # shared by all dogs
"canine"
>>> e.kind   # shared by all dogs
"canine"
>>> d.name   # unique to d
"Fido"
>>> e.name   # unique to e
"Buddy"
Run Code Online (Sandbox Code Playgroud)

解决方案

现在我们知道类变量由类的所有实例共享,我们可以简单地定义连接和光标,如下所示。

class Database(object):

   connection = None

   def __init__(self):
      if Database.connection is None:
         try:
            Database.connection = mysql.connector.connect(host="127.0.0.1", user="root", password="", database="db_test")
         except Exception as error:
            print("Error: Connection not established {}".format(error))
         else:
            print("Connection established")

   def execute_query(self, sql):
      cursor = Database.connection.cursor()
      cursor.execute(sql)
Run Code Online (Sandbox Code Playgroud)

因此,与数据库的连接在开始时创建一次,然后可供以后的每个实例使用。请注意,游标不会被缓存,因为创建游标基本上不需要时间。然而,创建连接的成本相当高,因此缓存它们是明智的。