best way to run python generator cleanup code

两盒软妹~` 提交于 2019-12-01 07:38:18

You can use a context manager and the with statement. contextlib provides 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

This will automatically call close() on dbc at the end of the with block, even if an exception has been raised.

Your version will run dbc.close() as soon as d is None, but not if an exception gets raised. You need a finally clause. This version is guaranteed to run dbc.close() even if an exception gets raised:

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()

One thing you could do is use a finally clause. Another option (that may be overkill here but is a useful thing to know about) is to make a class that works with the with statement:

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)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!