Python的MySQLdb的上下文管理器

con*_*lee 14 python mysql with-statement contextmanager

我习惯(被宠坏了?)python的SQLite接口来处理SQL数据库.python的SQLite API中的一个很好的特性是"上下文管理器",即python的with声明.我通常以下列方式执行查询:

import as sqlite

with sqlite.connect(db_filename) as conn:
    query = "INSERT OR IGNORE INTO shapes VALUES (?,?);"
    results = conn.execute(query, ("ID1","triangle"))
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,如果我的查询修改了数据库并且我忘记运行conn.commit(),则上下文管理器在退出with语句时自动为我运行它.它还可以很好地处理异常:如果在我提交任何内容之前发生异常,则回滚数据库.

我现在正在使用MySQLdb界面,它似乎不支持开箱即用的类似上下文管理器.我如何创建自己的?还有一个相关的问题在这里,但它并没有提供一个完整的解决方案.

unu*_*tbu 20

以前,MySQLdb连接是上下文管理器.由于该犯于2018年12月4日,然而,MySQLdb的连接不再是上下文管理器,用户必须显式调用conn.commit()或conn.rollback(),或写自己的上下文管理器,如下面的一个.


你可以使用这样的东西:

import config
import MySQLdb
import MySQLdb.cursors as mc
import _mysql_exceptions
import contextlib
DictCursor = mc.DictCursor
SSCursor = mc.SSCursor
SSDictCursor = mc.SSDictCursor
Cursor = mc.Cursor

@contextlib.contextmanager
def connection(cursorclass=Cursor,
               host=config.HOST, user=config.USER,
               passwd=config.PASS, dbname=config.MYDB,
               driver=MySQLdb):
    connection = driver.connect(
            host=host, user=user, passwd=passwd, db=dbname,
            cursorclass=cursorclass)
    try:
        yield connection
    except Exception:
        connection.rollback()
        raise
    else:
        connection.commit()
    finally:
        connection.close()

@contextlib.contextmanager
def cursor(cursorclass=Cursor, host=config.HOST, user=config.USER,
           passwd=config.PASS, dbname=config.MYDB):
    with connection(cursorclass, host, user, passwd, dbname) as conn:
        cursor = conn.cursor()
        try:
            yield cursor
        finally:
            cursor.close()


with cursor(SSDictCursor) as cur:
    print(cur)
    connection = cur.connection
    print(connection)
    sql = 'select * from table'
    cur.execute(sql)
    for row in cur:
        print(row)
Run Code Online (Sandbox Code Playgroud)

要使用它,您可以放入config.pyPYTHONPATH并在那里定义HOST,USER,PASS,MYDB变量.


小智 18

自从这个问题最初被问到以后,认为事情已经改变 有点令人困惑(至少从我的观点来看),对于最近的版本MySQLdb,如果你在上下文中使用连接你得到一个游标(根据oursql例子),而不是自动关闭的东西(就像你打开一个文件一样)例如).

这是我做的:

from contextlib import closing
with closing(getConnection()) as conn: #ensure that the connection is closed
    with conn as cursor:               #cursor will now auto-commit
        cursor.execute('SELECT * FROM tablename')
Run Code Online (Sandbox Code Playgroud)

  • 自动提交?就像自动提交模式一样,所以你没有事务? (2认同)