数据库访问生成器功能有优势吗?

时间:2012-07-27 15:17:22

标签: python generator mysql-python

在while循环中调用.fetchone()时,编写以下生成器函数是否有优势?如果是这样,那个优势会是什么?

感谢。

def testf2():
    db = connectToMysqlDB(None)

    sql_statement = " ".join([
        "select d.* ",
        "from dr_snapshot d ",
        "order by d.PremiseID asc, d.last_read asc; "])

    sel_cur = db.cursor()
    rc = sel_cur.execute(sql_statement)

    loop_ok = True
    while loop_ok:
        meter_row = sel_cur.fetchone()
        if meter_row:
            yield meter_row
        else:
            loop_ok = False

    yield None

for read_val in testf2():
   print(read_val)
   #Perform something useful other than print.

('610159000', 6, datetime.datetime(2012, 7, 25, 23, 0), 431900L, 80598726L)
('610160000', 6, datetime.datetime(2012, 7, 25, 23, 0), 101200L, 80581200L)
None

3 个答案:

答案 0 :(得分:4)

不。在功能上它们是相同的,但如果你想重用代码,将它包装在生成器中是有好处的。例如,您可以添加代码以在完成读取生成器块后关闭连接/光标。我建议您将其添加到上面的代码中,以便关闭游标。

def testf2():
    try:
        db = connectToMysqlDB(None)

        sql_statement = " ".join([
            "select d.* ",
            "from dr_snapshot d ",
            "order by d.PremiseID asc, d.last_read asc; "])

        sel_cur = db.cursor()
        rc = sel_cur.execute(sql_statement)

        loop_ok = True
        while loop_ok:
            meter_row = sel_cur.fetchone()
            if meter_row:
                yield meter_row
            else:
                loop_ok = False
    except ProgrammingError:
        print "Tried to read a cursor after it was already closed"
    finally:
        sel_cur.close()

这样可以更容易重用,因为您只需要在一个地方获得连接管理。

答案 1 :(得分:3)

看起来我是对的,mySQL游标 可迭代(https://stackoverflow.com/a/1808414/138772)。所以你可以这样做而不是你的while循环(但我喜欢把数据库访问代码放在生成器函数中的想法,所以保持这个):

for meter_row in sel_cur:
    yield meter_row

另请注意,您可能不希望最终yield None; StopIteration异常用于指示迭代器输出的耗尽,并且for循环用作停止循环的标志,因此通过包含yield None最终得到None输出结束时没有实际收益。

答案 2 :(得分:0)

使用生成器可以更灵活地在现有代码中使用结果。例如,您可以将其直接传递给csv.writer writerows函数。