在Python

时间:2015-05-17 15:23:28

标签: python mysql-python

我是Python及其MySQLdb连接器的新手。 我正在编写API以使用RESTful方法从数据库返回一些数据。在PHP中,我将Connection管理部分包装在一个类中,充当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
    

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

现在问题开始出现了:

  • 在一个函数中,我发出一个插入查询来创建一个'组'与独特的&groupid'。

  • 这个'组'有一个创造者。数据库中的每个用户都在'组中拥有一个JSON数组。他/她在表中的行的列。

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

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

  • 我已经将'插入'并且'更新'两个单独的函数defs中的部分。

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

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

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

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

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

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

我现在有以下问题:

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

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

2 个答案:

答案 0 :(得分:0)

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

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

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

# cursor closed.  Guaranteed.

connection.close()

目前,您必须使用Ctl+C中断您的计划,因为您的with声明没有理由停止运行。

其次,根据'交易开始考虑您与数据库的互动。做一些事情,将其提交给数据库,如果它没有工作,则回滚,如果确实如此,则关闭连接。 Here's a tutorial

答案 1 :(得分:0)

使用连接,与文件一样处理rule of thumb is open late, close early.

所以我建议只在他们尝试做一件事的地方分享联系。或者,如果您进行多处理,则每个进程都会获得一个连接,然后再次打开,然后提前关闭。如果你在循环外打开和关闭顺序操作(比如循环)。拥有全球联系可能会变得混乱。主要是因为现在你必须跟踪哪个函数在什么时候使用它,以及它尝试用它做什么。

“现在无法运行命令”的问题,是因为键盘中断会导致活动连接中断。

关于你的问题的第一部分 - 无休止地可以在任何地方。 python的每个实例都将获得自己的连接。因此,当你第二次运行它时,它应该得到自己的连接。打开一个mysql客户端并执行

show full processlist

看看最近发生了什么。