是在Python数据库API中指定的连接对象的__enter__和__exit__行为吗? [英] Is __enter__ and __exit__ behaviour for connection objects specified in the Python database API?

查看:160
本文介绍了是在Python数据库API中指定的连接对象的__enter__和__exit__行为吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近发现了使用关键字的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:


  1. MySQLdb的 __输入__ __ exit __ 连接对象?是 __ exit __ 去神奇地提交或回滚更改我没有我明确要求发生?

  2. 在Python数据库API的其他实现(如sqlite3,django或psycopg2)中,此行为是否相同?

  3. 这种行为在任何地方是正式的吗? ctrl-f 使用最新规范( PEP 249 - Python数据库API规范v2.0 )为'enter','exit'和'context manager'不会抛出任何东西。

  1. 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?
  2. Is this behaviour the same in other implementers of the Python database API (like sqlite3, django, or psycopg2)?
  3. Is this behaviour formally specced anywhere? ctrl-fing 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆