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

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

问题描述

背景

我最近与关键字发现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()作为光标:,否则不使用在所有

问题

紧随这一发现让我不知道的几件事情:


  1. 请别的什么 __ __输入 __ __退出 MySQLdb的连接对象的方法吗?为 __ __退出将神奇地提交或回滚我没有改变我明确要求要做到这一点?是否还有其他非显而易见的,我应该知道的?

  2. 这种行为是在Python数据库API的其他执行者(如sqlite3的,Django的,或psycopg2的)一样的吗?

  3. 这种行为在任何地方正式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上下文管理器实现是微妙的不同;它还管理事务,但不会从 __ __输入方法返回一个光标:

  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:

  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.

解决方案

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屋!

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