在 Python 中跨多个函数使用 MySQLdb 连接和游标的正确方法是什么

TBZ*_*Z92 5 python mysql-python

我对 Python 及其 MySQLdb 连接器有点陌生。我正在编写一个 API 来使用 RESTful 方法从数据库返回一些数据。在 PHP 中,我将连接管理部分封装在一个类中,充当 MySQL 查询的抽象层。

在 Python 中:

  • 我很早就在脚本中定义了连接: con = mdb.connect('localhost', 'user', 'passwd', 'dbname')

  • 然后,在所有后续方法中:

    import MySQLdb as mdb
    
    def insert_func():
    
    with con: 
    
    cur = con.cursor(mdb.cursors.DictCursor)
    cur.execute("INSERT INTO table (col1, col2, col3) VALUES (%s, %s, %s)", (val1, val2, val3) )
    
    rows = cur.fetchall()
    
    #do something with the results
    
    return someval
    
    Run Code Online (Sandbox Code Playgroud)

    等等。

  • 我使用mdb.cursors.DictCursor是因为我更喜欢能够以关联数组的方式访问数据库列。

现在问题开始出现:

  • 在一个函数中,我发出一个插入查询以创建一个具有唯一“groupid”的“组”。

  • 这个“组”有一个创建者。数据库中的每个用户都在表中他/她行的“组”列中保存一个 JSON 数组。

  • 因此,当我创建一个新组时,我想将 groupid 分配给创建它的用户。

  • 我使用类似的功能更新用户的记录。

  • 我已经将“插入”和“更新”部分包装在两个单独的函数定义中。

  • 我第一次运行脚本时,一切正常。

  • 第二次运行脚本时,脚本无休止地运行(我怀疑是由于与 MySQL 数据库的某些空闲连接)。

  • 当我使用 CTRL + C 中断它时,我收到以下错误之一:

    • “'Cursor' 对象没有属性 'connection'”
    • “命令不同步;你现在不能运行这个命令”
    • 或任何其他 KeyboardInterrupt 异常,正如预期的那样。

在我看来,这些错误是由我的代码中处理连接和游标的错误方式引起的。

我读到使用它是一种很好的做法,with con:这样连接将在查询后自动关闭。我在每个函数中的 'con' 上使用了 'with',所以连接是关闭的,但我决定全局定义连接,以便任何函数使用它。这似乎与with con:上下文管理不兼容。我怀疑游标需要以类似的方式进行“上下文管理”,但我不知道如何做到这一点(据我所知,PHP 不为 MySQL 使用游标,所以我没有使用它们的经验)。

我现在有以下问题:

  1. 为什么它第一次有效但第二次无效?(但是,它会在 CTRL + C 中断后再次工作一次)。

  2. 在使用多个函数(可以按顺序调用)时,我应该如何使用连接和游标?

Jar*_*red 0

我认为这里有两个主要问题——一个似乎是 python 代码,另一个是与数据库交互的结构。

首先,您没有关闭连接。这取决于您的应用程序的需求 - 您必须决定它应该保持打开状态多长时间。参考这个SO问题

from contextlib import closing
with closing( connection.cursor() ) as cursor:
    ... use the cursor ...

# cursor closed.  Guaranteed.

connection.close()
Run Code Online (Sandbox Code Playgroud)

现在,您必须中断您的程序,Ctl+C因为您的语句没有理由with停止运行。

其次,开始从“事务”的角度考虑您与数据库的交互。做一些事情,将其提交到数据库,如果不起作用,则回滚,如果起作用,则关闭连接。这是一个教程