我可以将 pymysql.connect() 与“with”语句一起使用吗?
Posted
技术标签:
【中文标题】我可以将 pymysql.connect() 与“with”语句一起使用吗?【英文标题】:Can I use pymysql.connect() with "with" statement? 【发布时间】:2015-09-21 18:12:44 【问题描述】:以下是pymysql中的示例:
conn = pymysql.connect(...)
with conn.cursor() as cursor:
cursor.execute(...)
...
conn.close()
我可以改用以下内容,还是会留下挥之不去的联系? (执行成功)
import pymysql
with pymysql.connect(...) as cursor:
cursor.execute('show tables')
(python 3,最新的pymysql)
【问题讨论】:
为什么不试试呢? 正如我所指出的,它执行成功。但是,如果可以做某事,并不一定意味着应该做 :) 我正在尝试确定是否应该这样做,否则会留下挥之不去的联系。 【参考方案1】:这看起来不安全,如果您查看 here,__enter__
和 __exit__
函数就是在 with
子句中调用的函数。对于 pymysql 连接,它们看起来像这样:
def __enter__(self):
"""Context manager that returns a Cursor"""
return self.cursor()
def __exit__(self, exc, value, traceback):
"""On successful exit, commit. On exception, rollback"""
if exc:
self.rollback()
else:
self.commit()
所以它看起来不像 exit 子句关闭连接,这意味着它会徘徊。我不确定他们为什么这样做。不过,您可以制作自己的包装器来执行此操作。
您可以通过创建多个游标来回收连接(the source for cursors is here)游标方法如下所示:
def __enter__(self):
return self
def __exit__(self, *exc_info):
del exc_info
self.close()
所以他们确实关闭了自己。您可以创建一个连接并在 with
子句中使用多个游标重复使用它。
如果你想在with
子句后面隐藏关闭连接的逻辑,例如一个上下文管理器,一个简单的方法是这样的:
from contextlib import contextmanager
import pymysql
@contextmanager
def get_connection(*args, **kwargs):
connection = pymysql.connect(*args, **kwargs)
try:
yield connection
finally:
connection.close()
然后您可以像这样使用该上下文管理器:
with get_connection(...) as con:
with con.cursor() as cursor:
cursor.execute(...)
【讨论】:
你在finally
子句中推荐con.commit() 吗?给定例如forums.mysql.com/read.php?50,578823,578941#msg-578941【参考方案2】:
正如所指出的,Cursor 会自行处理,但是几天前 Connection 对上下文管理器的所有支持都被完全删除了,所以现在唯一的选择就是编写你的:
https://github.com/PyMySQL/PyMySQL/pull/763
https://github.com/PyMySQL/PyMySQL/issues/446
【讨论】:
【参考方案3】:作为替代方案,因为我想支持连接的上下文管理器模式,所以我使用猴子补丁来实现它。不是最好的方法,但它是一些东西。
import pymysql
MONKEYPATCH_PYMYSQL_CONNECTION = True
def monkeypatch_pymysql_connection():
Connection = pymysql.connections.Connection
def enter_patch(self):
return self
def exit_patch(self, exc, value, traceback):
try:
self.rollback() # Implicit rollback when connection closed per PEP-249
finally:
self.close()
Connection.__enter__ = enter_patch
Connection.__exit__ = exit_patch
if MONKEYPATCH_PYMYSQL_CONNECTION:
monkeypatch_pymysql_connection()
MONKEYPATCH_PYMYSQL_CONNECTION = False # Prevent patching more than once
这种方法适用于我的用例。我希望在 Connection
类中有 __enter__
和 __exit__
方法。然而,开发人员在 2018 年底解决该问题时拒绝了这种方法。
【讨论】:
以上是关于我可以将 pymysql.connect() 与“with”语句一起使用吗?的主要内容,如果未能解决你的问题,请参考以下文章
执行 pymysql.connect 时出现错误 Keyerror 255