Python 使用生成器获取 MySQLdb 结果 block - 错误

标签 python generator mysql-python

我有以下代码:

def executeQuery(conn, query):
    cur = conn.cursor()
    cur.execute(query)
    return cur

def trackTagsGenerator(chunkSize, baseCondition):
    """ Returns a dict of trackId:tag limited to chunkSize. """

    sql = """
        SELECT track_id, tag
        FROM tags 
        WHERE {baseCondition}
    """.format(baseCondition=baseCondition)

    limit = chunkSize
    offset = 0
    while True:
        trackTags = {}

        # fetch the track ids with the coresponding tag
        limitPhrase = " LIMIT %d OFFSET %d" % (limit, offset)
        query = sql + limitPhrase
        offset += limit
        cur = executeQuery(smacConn, query)
        rows = cur.fetchall()

        if not rows:
            break

        for row in rows:
            trackTags[row['track_id']] = row['tag']

        yield trackTags

我想这样使用它:

for trackTags in list(trackTagsGenerator(DATA_CHUNK_SIZE, baseCondition)):        
    print trackTags
    break

此代码甚至没有获取一大块轨道标签就会产生以下错误:

Exception _mysql_exceptions.ProgrammingError: (2014, "Commands out of sync; you can't run this command now") in <bound method SSDictCursor.__del__ of <MySQLdb.cursors.SSDictCursor object at 0x10b067b90>> ignored

我怀疑这是因为我在生成器函数的循环体中有查询执行逻辑。

有人能告诉我如何使用 mysqldb 以这种方式获取数据 block 吗?

最佳答案

我很确定这是因为它可能会遇到有两个查询的情况 由于产量而同时运行。根据您调用函数的方式(线程、异步等),我很确定您的光标也可能会被破坏?

此外,您实际上是通过使用 printf 插入 baseConditional 来暴露自己(抱歉,但我无法粉饰这部分)可怕的 SQL 注入(inject)漏洞。查看 DB-API 的参数替换文档以获取帮助。

Yield 根本不会为您节省时间或精力,在您获得单个结果之前,始终需要运行完整的 sql 命令。 (因此,您使用 LIMIT 和 OFFSET 来使其更加友好,值得称赞)

即当您生成一些数据时,有人更新了表,在这种特殊情况下 - 不是世界末日。在许多其他情况下,它会变得丑陋。

如果你只是闲逛,并且希望它“立即生效”,那么修改executeQuery可能会起作用:

 def executeQuery(conn, query):
     cur = conn.cursor()
     cur.execute(query)
     cur = executeQuery(smacConn, query)
     rows = cur.fetchall()
     cur.close()
     return rows

有一件事也让我感到惊讶 - 你定义了 trackTags = {},但随后你更新了 tagTrackIds,并产生了 trackTags.. 这将永远是空的字典。

我的建议是,如果您只是想让一个业余爱好项目发挥作用,就不要为手写 SQL 的麻烦而烦恼。看看Elixir它建立在 SQLAlchemy 之上。

使用 ORM(对象关系映射器)可以更友好地介绍数据库。在 Python 中定义对象的外观,并让它自动为您生成模式 - 并且能够以 Pythonic 方式添加/修改/删除内容真的很漂亮。

如果您确实需要异步,请查看 ultramysql python 模块。

关于Python 使用生成器获取 MySQLdb 结果 block - 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13343432/

相关文章:

javascript - 链接异步方法调用 - javascript

python - 迭代两个不同长度的生成器,其中一个环绕

python - 打印 MySQLdb 运行的实际查询?

django - 为 Django 安装 MySQL-python

python - Stash 标签上的 DELETE 请求

python - Python/C API 中的内存泄漏和引用计数

python - 根据另一列向日期添加一天

python - 内容类型 text/plain 的文件扩展名为 .ksh?

HTML 注释生成器

python - 在 Python 中将用户输入与 mysql 数据库值进行比较