使用以下代码会使我保留一个打开的连接,如何关闭?
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
使用以下代码会使我保留一个打开的连接,如何关闭?
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
根据PEP-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
的 connection 和 cursor 都是上下文管理器,所以现在更方便(也更可取)的写法是:
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 contextlib
更改为from contextlib import contextmanager
或者将你的装饰器更改为@contextlib.contextmanager
。两种方法都可以,但我更喜欢前者。 - jedmaoself.db = pyodbc.connect(path)
,现在当我想要覆盖它到你的方式:self.db = open_db_connection("...")
或者其他任何方式时,我的连接在初始化后立即关闭了 pyodbc.ProgrammingError: The cursor's connection has been closed.
- (而我希望在整个运行时都保持连接)。 - Intelligent-Infrastructure您可以尝试关闭连接池,它默认是开启的。有关更多信息,请参见此讨论。
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
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())
https://dev59.com/ZloT5IYBdhLWcg3w4CiO#38078544
。 - Tomyimport pyodbc
pyodbc.pooling = False
如果语言没有像 .NET 中的 Using
这样的自关闭结构,则处理连接的最常见方法是使用 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
del
。它确实会关闭游标,但通常情况下并不必要,因为当csr
超出作用域时,同样的操作会自动发生(而且通常很快)。只有在想要从命名空间中删除csr
和/或将对该对象的引用减少一个时才使用它。当我第一次发布这篇文章时,我保留了del
,因为它并不一定是错误的,而且我认为OP理解了它的目的。但由于它似乎引起了混淆,并且不需要关闭连接,所以现在我将其删除。 - unutbuwith
语句吗? - NoName