Python数据库连接关闭

Mer*_*lin 48 python database-connection

使用下面的代码让我打开一个连接,如何关闭?

import pyodbc
conn = pyodbc.connect('DRIVER=MySQL ODBC 5.1 driver;SERVER=localhost;DATABASE=spt;UID=who;PWD=testest') 

csr = conn.cursor()  
csr.close()
del csr
Run Code Online (Sandbox Code Playgroud)

unu*_*tbu 58

Connections具有closePEP-249(Python数据库API规范v2.0)中指定的方法:

import pyodbc
conn = pyodbc.connect('DRIVER=MySQL ODBC 5.1 driver;SERVER=localhost;DATABASE=spt;UID=who;PWD=testest') 

csr = conn.cursor()  
csr.close()
conn.close()     #<--- Close the connection
Run Code Online (Sandbox Code Playgroud)

  • 这是最佳实践吗?要手动关闭游标,然后删除它,然后关闭连接? (2认同)
  • 与上下文管理器一起使用时,pyodbc 对象不会自动关闭!正如您链接到的文档指出的那样,使用上下文管理器语法相当于提交但不关闭连接或游标。请参阅 https://github.com/mkleehammer/pyodbc/issues/43 (2认同)

And*_*ewF 52

您可以将整个连接包装在上下文管理器中,如下所示:

from contextlib import contextmanager
import pyodbc
import sys

@contextmanager
def open_db_connection(connection_string, commit=False):
    connection = pyodbc.connect(connection_string)
    cursor = connection.cursor()
    try:
        yield cursor
    except pyodbc.DatabaseError as err:
        error, = err.args
        sys.stderr.write(error.message)
        cursor.execute("ROLLBACK")
        raise err
    else:
        if commit:
            cursor.execute("COMMIT")
        else:
            cursor.execute("ROLLBACK")
    finally:
        connection.close()
Run Code Online (Sandbox Code Playgroud)

然后在需要数据库连接的地方执行以下操作:

with open_db_connection("...") as cursor:
    # Your code here
Run Code Online (Sandbox Code Playgroud)

离开with区块时,连接将关闭.如果发生异常或未使用打开块,这也将回滚事务with open_db_connection("...", commit=True).


Mat*_*kin 7

您可以尝试关闭池,默认情况下启用池.有关更多信息,请参阅讨论.

import pyodbc
pyodbc.pooling = False
conn = pyodbc.connect('DRIVER=MySQL ODBC 5.1 driver;SERVER=localhost;DATABASE=spt;UID=who;PWD=testest') 

csr = conn.cursor()  
csr.close()
del csr
Run Code Online (Sandbox Code Playgroud)


小智 6

您可以如下定义数据库类。另外,正如andrewf建议的那样,使用上下文管理器进行游标访问。我将其定义为成员函数。这样,它可以在应用程序代码的多个事务中保持连接打开,并避免与服务器不必要的重新连接。

import pyodbc

class MS_DB():
    """ Collection of helper methods to query the MS SQL Server database.
    """

    def __init__(self, username, password, host, port=1433, initial_db='dev_db'):
        self.username = username
        self._password = password
        self.host = host
        self.port = str(port)
        self.db = initial_db
        conn_str = 'DRIVER=DRIVER=ODBC Driver 13 for SQL Server;SERVER='+ \
                    self.host + ';PORT='+ self.port +';DATABASE='+ \
                    self.db +';UID='+ self.username +';PWD='+ \ 
                    self._password +';'
        print('Connected to DB:', conn_str)
        self._connection = pyodbc.connect(conn_str)        
        pyodbc.pooling = False

    def __repr__(self):
        return f"MS-SQLServer('{self.username}', <password hidden>, '{self.host}', '{self.port}', '{self.db}')"

    def __str__(self):
        return f"MS-SQLServer Module for STP on {self.host}"

    def __del__(self):
        self._connection.close()
        print("Connection closed.")

    @contextmanager
    def cursor(self, commit: bool = False):
        """
        A context manager style of using a DB cursor for database operations. 
        This function should be used for any database queries or operations that 
        need to be done. 

        :param commit:
        A boolean value that says whether to commit any database changes to the database. Defaults to False.
        :type commit: bool
        """
        cursor = self._connection.cursor()
        try:
            yield cursor
        except pyodbc.DatabaseError as err:
            print("DatabaseError {} ".format(err))
            cursor.rollback()
            raise err
        else:
            if commit:
                cursor.commit()
        finally:
            cursor.close()

ms_db = MS_DB(username='my_user', password='my_secret', host='hostname')
with ms_db.cursor() as cursor:
        cursor.execute("SELECT @@version;")
        print(cur.fetchall())
Run Code Online (Sandbox Code Playgroud)