Python MySQLdb 的“with”语法和 DictCursor

1 投票
3 回答
1804 浏览
提问于 2025-04-17 15:54

我正在尝试在一个 DictCursor 的上下文中使用 with 语句。 我本以为使用:

with MySQLdb.connect(...) as c:

c 应该是一个连接对象,因为这就是 connect() 返回的结果。 可是,结果并不是这样! 突然间,c 变成了一个游标! 虽然这通常很方便,但我真的很喜欢使用 DictCursor - 这难道根本不是这样设计的吗? 把 DictCursor 放在 "作用域对象" 中会导致错误(__exit__ 没有定义)

3 个回答

0

我对使用sqlalchemy处理原始sql的解决办法

if self.engine.url.drivername == 'mysql+pymysql':
    from pymysql.cursors import SSDictCursor
    connection = self.engine.raw_connection()
    cursor = connection.cursor(cursor=SSDictCursor)
elif self.engine.url.drivername == 'mysql+mysqldb':
    import MySQLdb.cursors
    connection = self.engine.raw_connection()
    cursor = connection.cursor(cursorclass=MySQLdb.cursors.DictCursor)
else:
    connection = self.engine.raw_connection()
    cursor = connection.cursor()

或者在创建连接时使用

connect_args=dict(cursorclass=MySQLdb.cursors.DictCursor)
1

c 是一个游标,因为它是上下文管理器的 __enter__ 方法返回的东西。
如果你查看 Mysqldb 的源代码,就能在 connections.py 文件的第 245 行 看到相关内容:

def __enter__(self): return self.cursor()

至于 DictCursor,它不支持上下文管理。

2

根据MySQLdb中对连接的定义,在这里可以查看connections.py的第254行,Connection.cursor()会返回一个Connection.cursorclass的实例:

def cursor(self, cursorclass=None):
    """
    Create a cursor on which queries may be performed. The
    optional cursorclass parameter is used to create the
    Cursor. By default, self.cursorclass=cursors.Cursor is
    used.
    """
    return (cursorclass or self.cursorclass)(self)

所以,我猜如果你在初始化连接的时候,使用了“cursorclass”这个参数,并把它设置为MySQLdb.cursors.DictCursor,比如:

dbconn = MySQLdb.connect(cursorclass=MySQLdb.cursors.DictCursor)

当你这样做的时候

def __enter__(self):
    if self.get_autocommit():
        self.query("BEGIN")
    return self.cursor()

它就会返回一个字典类型的游标。

撰写回答