簡體   English   中英

Python 數據庫連接關閉

[英]Python Database connection Close

使用下面的代碼讓我有一個打開的連接,我該如何關閉?

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

連接具有 PE​​P-249(Python 數據庫 API 規范 v2.0)中指定的close方法:

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

由於pyodbc 連接游標都是上下文管理器,現在將其寫為更方便(也更可取):

import pyodbc
conn = pyodbc.connect('DRIVER=MySQL ODBC 5.1 driver;SERVER=localhost;DATABASE=spt;UID=who;PWD=testest') 
with conn:
    crs = conn.cursor()
    do_stuff
    # conn.commit() will automatically be called when Python leaves the outer `with` statement
    # Neither crs.close() nor conn.close() will be called upon leaving the `with` statement!! 

請參閱https://github.com/mkleehammer/pyodbc/issues/43以了解為什么不調用 conn.close() 的解釋。

請注意,與原始代碼不同,這會導致conn.commit() 使用外部with語句來控制何時要調用commit


另請注意,無論您是否使用with語句,根據文檔

連接被刪除時會自動關閉(通常是當它們超出范圍時),因此您通常不需要調用 [ conn.close() ],但如果您願意,您可以明確關閉連接。

游標類似(我的重點):

游標在被刪除時會自動關閉(通常是當它們超出范圍時),因此通常不需要調用 [ csr.close() ]

您可以將整個連接包裝在上下文管理器中,如下所示:

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()

然后在需要數據庫連接的地方執行以下操作:

with open_db_connection("...") as cursor:
    # Your code here

當您離開 with 塊時,連接將關閉。 如果發生異常或者您沒有使用with open_db_connection("...", commit=True)打開塊,這也將回滾事務。

您可以嘗試關閉默認情況下啟用的池。 有關更多信息,請參閱討論。

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

根據 pyodbc 文檔, 默認情況下不會關閉與 SQL 服務器的連接 某些數據庫驅動程序在調用 close() 時不會關閉連接,以保存與服務器的往返。

要在調用close()時關閉連接,您應該將 pooling 設置為 False:

import pyodbc

pyodbc.pooling = False

您可以定義一個數據庫類,如下所示。 另外,正如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())

處理連接的最常用方法,如果語言沒有像Using in .NET 這樣的自關閉結構,那么您應該使用 try -> finally 來關閉對象。 pyodbc 可能有某種形式的自動關閉,但這里是我做的代碼,以防萬一:

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

    cursor = conn.cursor()  

    # ... do stuff ...

finally:
    try: cursor.close()
    except: pass
    try: conn.close()
    except: pass

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM