是在Python数据库API中指定的连接对象的__enter__和__exit__行为吗? [英] Is __enter__ and __exit__ behaviour for connection objects specified in the Python database API?
问题描述
我最近发现了使用关键字的Python ,并开始看到它更有效地处理某些方案,我以前使用
try:... finally:...
构造。我立即决定在MySQLdb连接对象上尝试一下我正在编写的代码。
I recently discovered the Python with
keyword and started seeing its potential usefulness for more prettily handling some scenarios where I'd previously have used try: ... finally: ...
constructs. I immediately decided to try it out on the MySQLdb connection object in some code I was writing.
我没有打扰如何 __ enter__
和 __ exit __
在Python数据库API的实现中行为,天真地预期行为像文件对象的行为 - 我所期望的是退出以调用 connection.close()
。
I didn't bother reading up on how __enter__
and __exit__
behave in implementors of the Python database API, and naively expected the behaviour to be like that of file objects - all I was expecting was for exit to call connection.close()
.
想象我的困惑, >
Imagine my confusion, then, at this behaviour:
>>> with util.get_db_connection() as conn:
... print conn
...
<MySQLdb.cursors.Cursor object at 0xb6ca8b4c>
get_db_connection()
返回MySQLdb连接对象,但是该连接对象的 __ enter __
方法返回一个游标对象,而不是我期望的连接对象本身,如何 __ enter __
和 __ exit __
用于文件对象。我想我应该使用util.get_db_connection()作为游标:,或者不使用与 。
get_db_connection()
returns a MySQLdb connection object, but the __enter__
method of that connection object returns a cursor object, not the connection object itself like I was expecting given how __enter__
and __exit__
work for file objects. I guess I ought to be doing with util.get_db_connection() as cursor:
, or else not using with
at all.
这个发现立即让我想起了几件事:
Immediately this discovery makes me wonder a few things:
- MySQLdb的
__输入__
和__ exit __
连接对象?是__ exit __
去神奇地提交或回滚更改我没有我明确要求发生? - 在Python数据库API的其他实现(如sqlite3,django或psycopg2)中,此行为是否相同?
- 这种行为在任何地方是正式的吗?
ctrl-f
使用最新规范( PEP 249 - Python数据库API规范v2.0 )为'enter','exit'和'context manager'不会抛出任何东西。
- What else do the
__enter__
and__exit__
methods of MySQLdb connection objects do? Is__exit__
going to magically commit or rollback changes for me without me explicitly asking for that to happen? Is there anything else non-obvious that I should know? - Is this behaviour the same in other implementers of the Python database API (like sqlite3, django, or psycopg2)?
- Is this behaviour formally specced anywhere?
ctrl-f
ing the latest spec (PEP 249 -- Python Database API Specification v2.0) for 'enter', 'exit' and 'context manager' doesn't throw up anything.
推荐答案
Python DBAPI在将上下文管理器添加到Python语言之前编写得很好。
The Python DBAPI was written well before context managers were added to the Python language.
因此,不同的数据库库如何实现上下文管理器支持(如果他们实现上下文管理器支持)就会自己决定。
As such, different database libraries made their own decisions on how to implement context manager support (if they implemented it at all).
通常使用数据库作为上下文管理器将您绑定到事务。事务在 __ enter __
上启动,并在 __ exit __
上提交或中止,这取决于是否有异常。因此,您应该在连接后使用MySQL连接作为上下文管理器:
Usually using the database as a context manager ties you to a transaction. The transaction is started on __enter__
, and committed or aborted on __exit__
, depending on wether or not there was an exception. As such, you are supposed to use the MySQL connection as a context manager after connecting seperately:
connection = util.get_db_connection()
with connection as cursor:
cursor.execute(...)
# connection commit is issued if no exceptions were raised.
sqlite3
上下文管理器实现略有不同;它也管理事务,但不从 __ enter __
方法返回游标:
The sqlite3
context manager implementation is subtly different; it also manages transactions, but does not return a cursor from the __enter__
method:
con = sqlite3.connect(":memory:")
with con:
cursor = con.cursor()
# or use the connection directly
con.execute(...)
技术上,它只是返回 self
在 __ enter __
。
Technically, it just returns self
on __enter__
.
这篇关于是在Python数据库API中指定的连接对象的__enter__和__exit__行为吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!