背景
我最近发现了 Pythonwith
关键字,并开始看到它在更漂亮地处理一些我以前使用过try: ... finally: ...
构造的场景方面的潜在用途。我立即决定在我正在编写的一些代码中对 MySQLdb 连接对象进行尝试。
我没有费心去阅读Python 数据库 API 的实现者的行为方式__enter__
和__exit__
行为方式,并且天真地期望这种行为类似于文件对象的行为——我所期望的只是 exit 调用connection.close()
.
那么,想象一下我对这种行为的困惑:
>>> with util.get_db_connection() as conn:
... print conn
...
<MySQLdb.cursors.Cursor object at 0xb6ca8b4c>
get_db_connection()
返回一个 MySQLdb 连接对象,但该__enter__
连接对象的方法返回一个游标对象,而不是我所期望的连接对象本身,因为文件对象的方式__enter__
和__exit__
工作方式。我想我应该这样做with util.get_db_connection() as cursor:
,否则根本不使用with
。
问题
这个发现立刻让我想知道一些事情:
__enter__
MySQLdb 连接对象的和方法还有什么__exit__
作用?是否__exit__
会在没有我明确要求的情况下为我神奇地提交或回滚更改?还有什么我应该知道的不明显的吗?- 这种行为在 Python 数据库 API 的其他实现者(如 sqlite3、django 或 psycopg2)中是否相同?
- 这种行为在任何地方都有正式规定吗?
ctrl-f
为 'enter'、'exit' 和 'context manager' 制定最新规范(PEP 249 -- Python Database API Specification v2.0)并没有抛出任何东西。