运行 python 生成器清理代码的最佳方法

问题描述 投票:0回答:3

我正在尝试编写一个生成器函数,该函数从数据库中获取行并一次返回一行。但是,我不确定下面标记为 ** 的清理代码是否按照我的想法执行。如果没有,将清理代码放入生成器本身并在最后一个yield语句之后执行的最佳方法是什么?我查看了捕获 StopIteration 但这似乎是由调用者完成的,而不是在生成器内完成的。

def MYSQLSelectGenerator(stmt):
    ...
    try:   
        myDB = MySQLdb.connect(host=..., port=..., user=..., passwd=..., db=...)   
        dbc=myDB.cursor()
        dbc.execute(stmt)
        d = "asdf"
        while d is not None:
            d = dbc.fetchone() #can also use fetchmany() to be more efficient
            yield d
        dbc.close() #** DOES THIS WORK AS I INTEND, MEANING AS SOON AS d = "None"
    except MySQLdb.Error, msg:
        print("MYSQL ERROR!")
        print msg
python generator mysql-python
3个回答
5
投票

您的版本将在

dbc.close()
后立即运行
d is None
,但 如果引发异常则不会运行。您需要一个
finally
子句
。即使引发异常,此版本也保证运行
dbc.close()

try:   
    myDB = MySQLdb.connect(host=..., port=..., user=..., passwd=..., db=...)   
    dbc = myDB.cursor()
    dbc.execute(stmt)
    d = "asdf"
    while d is not None:
        d = dbc.fetchone() #can also use fetchmany() to be more efficient
        yield d
except MySQLdb.Error, msg:
    print("MYSQL ERROR!")
    print msg
finally:
    dbc.close()

5
投票

您可以做的一件事是使用

finally
子句。另一种选择(这里可能有点过分,但了解一下很有用)是创建一个与
with
语句一起使用的类:

class DatabaseConnection:
    def __init__(self, statement):
        self.statemet = statement
    def __enter__(self): 
        self.myDB = MySQLdb.connect(host=..., port=...,user=...,passwd=...,db=...)
        self.dbc = myDB.cursor()
        self.dbc.execute(self.statement)
        self.d = "asdf"
    def __exit__(self, exc_type, exc_value, traceback):
        self.dbc.close()

    def __iter__(self):
        while self.d is not None:
            self.d = self.dbc.fetchone()
            yield self.d


with DatabaseConnection(stmnt) as dbconnection:
    for i in dbconnection:
        print(i)

4
投票

您可以使用上下文管理器和

with
语句。
contextlib
提供
closing
:

from contextlib import closing

myDB = MySQLdb.connect(host=..., port=..., user=..., passwd=..., db=...)   
with closing(myDB.cursor()) as dbc:
    dbc.execute(stmt)
    d = "asdf"
    while d is not None:
        d = dbc.fetchone() #can also use fetchmany() to be more efficient
        yield d

即使已引发异常,这也会在

close()
块末尾自动调用
dbc
上的
with

© www.soinside.com 2019 - 2024. All rights reserved.