是__enter__和Python的数据库API中指定的连接对象__exit__行为? [英] Is __enter__ and __exit__ behaviour for connection objects specified in the Python database API?
问题描述
背景
我最近与关键字发现Python的,并开始看到它的潜在用途更多prettily处理的一些情形我倒是previously已经使用
尝试:...终于...
结构。我当即决定尝试一下在一些code我在写MySQLdb的连接对象上。
我没有理会如何 __进入阅读了__
和 __退出__
表现在Python数据库API的实现者,并天真地期望的行为,是这样的文件中的对象 - 我所期待是退出调用的Connection.close()
想象一下,我的困惑,那么,在这个行为:
>>>与util.get_db_connection()作为康恩:
...打印康恩
...
< MySQLdb.cursors.Cursor在0xb6ca8b4c&GT对象;
get_db_connection()
返回一个MySQLdb的连接对象,但 __进入__
的连接对象的方法返回一个游标对象,而不是连接对象本身就像我期待给如何 __进入__
和 __退出__
文件对象的工作。我想我应该做与util.get_db_connection()作为光标:
,否则不使用与
在所有
问题
紧随这一发现让我不知道的几件事情:
- 请别的什么
__ __输入
和__ __退出
MySQLdb的连接对象的方法吗?为__ __退出
将神奇地提交或回滚我没有改变我明确要求要做到这一点?是否还有其他非显而易见的,我应该知道的? - 这种行为是在Python数据库API的其他执行者(如sqlite3的,Django的,或psycopg2的)一样的吗?
- 这种行为在任何地方正式specced?
CTRL-F
ING最新的规范(的 PEP 249 - Python数据库API规范V2.0 )的进入,退出和情景管理不扔任何东西
Python的DBAPI是上下文管理器被添加到Python语言编写之前很好。
因此,不同的数据库库做了他们的的的关于如何实现上下文管理器的支持(如果他们付诸实施的话)的决定。
的通常的使用数据库作为上下文管理的关系你交易。该交易开始在 __进入__
,并提交或中止对 __退出__
,取决于羯羊或不存在是一个例外。因此,你应该单独连接后使用MySQL连接作为上下文管理器:
连接= util.get_db_connection()与连接,光标:
cursor.execute(...)#连接提交发出,如果没有异常曾引起。
的<一个href=\"http://docs.python.org/2/library/sqlite3.html#using-the-connection-as-a-context-manager\"><$c$c>sqlite3$c$c>上下文管理器实现是微妙的不同;它还管理事务,但不会从 __ __输入
方法返回一个光标:
CON = sqlite3.connect(:记忆:)
与CON:
光标= con.cursor()
#或者直接使用连接
con.execute(...)
从技术上讲,它只是返回自
在 __ __输入
。
Background
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.
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()
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.
Questions
Immediately this discovery makes me wonder a few things:
- 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.
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).
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.
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(...)
Technically, it just returns self
on __enter__
.
这篇关于是__enter__和Python的数据库API中指定的连接对象__exit__行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!