使用装饰器在SQLAlchemy中创建引擎

时间:2019-03-25 22:37:12

标签: python sqlalchemy

我的MySQL服务器上有几个数据库实例,我想创建一个小型库来使用它们。所有DB具有相同的结构-具有相同列的相同表。我使用SQLAlchemy处理该数据库,但无法使用一个引擎同时建立与多个数据库的连接。因此,让我们举个例子:

+----------+
| Database |
+----------+
| DB1      |
| DB2      |
| DB3      |
| DB4      |
+----------+

它们都具有以下结构:

+----------------+
| Tables_in_DB_N |
+----------------+
| table_1        |
| table_2        |
| table_3        |
+----------------+

因此,我想到了使用装饰器创建引擎和Session类的想法:

Session = None
def decor(func, user=USERNAME, passw=PASSWORD, host=HOSTNAME, port=POST, db=DB):
    def real_decor(func):
        def wrapper(*args, **kwargs):
            engine = create_engine('mysql+mysqlconnector://{user}:{passw}@{host}:{port}/{db}'.format(user=user, passw=passw, host=host, port=port, db=db))
            global Session
            Session = sessionmaker(bind=engine)
            return func(*args, **kwargs)
        return wrapper
    return real_decor

并使用以下装饰器示例进行功能:

@decor(db='DB1')
def get_db1_table1_values():
    session = Session()
    values = session.query(Table1).all()
    session.close()
    return values

此解决方案有效。我不太喜欢使用global Session进行入侵......,还有其他方法可以实现此功能吗?

1 个答案:

答案 0 :(得分:2)

这是一个有趣的问题,在不了解应用程序生命周期的情况下,很难找到适合您用例的解决方案,但这是一种尝试:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="init_ep_table">
  <tr>
					<td>
						<div class="input-group">
		                    <input type="text" class="form-control textmodify_newSchedule datepicker_recurring_start" > 
		                    <span class="input-group-addon ep_date4_calender datepicker_recurring_start_calender"><span class="glyphicon glyphicon-calendar"></span></span>
		                </div>
		            </td>
		            <td>
		            	<textarea></textarea>
		            </td>
		            <td>
		            	<input type="hidden" value="False"><input type="checkbox" class="cmpl_checkbox">
		            </td>
				</tr>
</table>
<input type="button" class="add_initep_row" value="Add Row">

使用此装饰器,它将会话直接注入到调用函数中,并避免使用def another_decor(user=USERNAME, passw=PASSWORD, host=HOSTNAME, port=PORT, db=DB): def real_decor(func): def wrapper(*args, **kwargs): engine = create_engine('mysql+mysqlconnector://{user}:{passw}@{host}:{port}/{db}'.format(user=user, passw=passw, host=host, port=port, db=db)) session = sessionmaker(bind=engine) return func(session, *args, **kwargs) return wrapper return real_decor 关键字。为此,需要这样定义数据库访问功能:

global

根据SQLAlchemy如何管理其数据库连接,使用自己的@another_decor(db='three') def get_three_table1_values(session): session = session() query = session.query(Table1).all() session.close() return query Engine装饰每个数据库访问功能,很容易耗尽与数据库的连接。

MySQL通常在内存中运行,并且基于SQLAlchemys documentation,我认为它将合并连接。所以这种用法可能没问题。