best way to run python generator cleanup code

后端 未结 3 704
鱼传尺愫
鱼传尺愫 2021-01-14 00:41

I\'m trying to write a generator function that gets rows out of a database and returns them one at a time. However, I\'m not sure if the cleanup code marked ** below execute

相关标签:
3条回答
  • 2021-01-14 00:47

    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.

    0 讨论(0)
  • 2021-01-14 00:51

    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()
    
    0 讨论(0)
  • 2021-01-14 01:11

    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)
    
    0 讨论(0)
提交回复
热议问题