关闭SQLAlchemy连接

时间:2014-08-27 23:19:53

标签: python sqlalchemy

我在python中有以下功能:

def add_odm_object(obj, table_name, primary_key, unique_column):
    db = create_engine('mysql+pymysql://root:@127.0.0.1/mydb')
    metadata = MetaData(db)
    t = Table(table_name, metadata, autoload=True)
    s = t.select(t.c[unique_column] == obj[unique_column])    
    rs = s.execute()
    r = rs.fetchone()
    if not r:
        i = t.insert()
        i_res = i.execute(obj)
        v_id = i_res.inserted_primary_key[0]
        return v_id
    else:
        return r[primary_key]   

此函数查看对象obj是否在数据库中,如果找不到,则将其保存到数据库。现在,我有一个问题。我多次在循环中调用上面的函数。几百次之后,我收到一个错误:user root has exceeded the max_user_connections resource (current value: 30)我尝试搜索答案,例如问题:How to close sqlalchemy connection in MySQL建议创建一个conn = db.connect()对象,其中db是我的查询完成后引擎并调用conn.close()

但是,我应该在哪里打开和关闭代码中的连接?我没有直接使用该连接,但我在代码中使用了Table()MetaData函数。

1 个答案:

答案 0 :(得分:1)

对于数据库连接,引擎是一个昂贵的创建factory。您的应用程序应该为每个数据库服务器调用create_engine() 一次

同样,MetaDataTable对象描述了已知数据库中的固定架构对象。这些也是配置构造,在大多数情况下,在模块中创建一次,就像类一样。

在这种情况下,你的函数似乎想要动态加载表,这很好; MetaData对象充当registry,它具有便利功能,如果已存在,它将为您提供现有表格。

在Python函数中,特别是在循环中,为了获得最佳性能,您通常只想引用一个数据库连接

考虑到这些因素,您的模块可能如下所示:

# module level variable.  can be initialized later, 
# but generally just want to create this once.
db = create_engine('mysql+pymysql://root:@127.0.0.1/mydb')

# module level MetaData collection.
metadata = MetaData()

def add_odm_object(obj, table_name, primary_key, unique_column):
    with db.begin() as connection:

        # will load table_name exactly once, then store it persistently
        # within the above MetaData
        t = Table(table_name, metadata, autoload=True, autoload_with=conn)

        s = t.select(t.c[unique_column] == obj[unique_column])    
        rs = connection.execute(s)
        r = rs.fetchone()
        if not r:
            i_res = connection.execute(t.insert(), some_col=obj)
            v_id = i_res.inserted_primary_key[0]
            return v_id
        else:
            return r[primary_key]