Python 使用全局数据库实例实现SQLAlchemy

Python 使用全局数据库实例实现SQLAlchemy,python,flask,sqlalchemy,flask-sqlalchemy,Python,Flask,Sqlalchemy,Flask Sqlalchemy,以下是我所做的: from flask import Flask from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker dbhost = 'localhost' dbuser = 'user' dbpass = 'password' dbname = 'db' DBUri = 'mysql://%s:%s@%s/%s?charset

以下是我所做的:

    from flask import Flask
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker

    dbhost = 'localhost'
    dbuser = 'user'
    dbpass = 'password'
    dbname = 'db'
    DBUri = 'mysql://%s:%s@%s/%s?charset=utf8'%(dbuser,dbpass,dbhost,dbname)

    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = (DBUri)
    app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'


    # an Engine, which the Session will use for connection
    # resources
    engine = create_engine(DBUri)

    # create a configured "Session" class
    Session = sessionmaker(bind=engine)

    # create a Session
    DBsession = Session()

@sched.cron_时间表(秒='*/5')
定义一些任务():
date\u now=datetime.datetime.now().date()
对于DBsession.query(用户组\u n\u主机)中的项。筛选器(用户组\u n\u主机.end\u时间
有一个表用户组\u n\u主机上面的代码是每30秒运行一次的函数

我的问题是,一旦我在那时启动了Flask应用程序,如果用户组\u n\u主机有10条记录,那么无论从外部将多少条记录插入表用户组\u n\u主机,上述代码都将继续打印10条记录。换句话说,我认为我的函数有一个表的实例,它只是在应用程序初始化的开始时初始化的。 我知道我在做傻事。请有人指出

代替
DBsession.query(user\u groups\u n\u hosts).filter(user\u groups\u n\u hosts.end\u time
我尝试了
user\u groups\u n\u hosts.query.filter(user\u groups\u n\u hosts.end\u time

但是结果是一样的。

您的筛选用户\u groups\u n\u hosts.end\u time

此外,您应该将会话视为每个请求的事情,而不是整个应用程序中的持久性实体。

记住这一点,试着改变

@sched.cron_schedule(second='*/5')
def some_decorated_task():
    date_now = datetime.datetime.now().date()
    for item in DBsession.query(user_groups_n_hosts).filter(user_groups_n_hosts.end_time < str(date_now)): 
        print item.id, item.server_users.native_linux_user
@sched.cron_时间表(秒='*/5')
定义一些任务():
date\u now=datetime.datetime.now().date()
对于DBsession.query(用户组\u n\u主机)中的项。筛选器(用户组\u n\u主机.end\u时间

@sched.cron_时间表(秒='*/5')
定义一些任务():
date\u now=datetime.datetime.now().date()
sess=会话()
对于sess.query(user\u groups\u n\u hosts).filter(user\u groups\u n\u hosts.end\u time
您每次都需要建立一个新的事务。 您可以在每次运行时创建一个全新的session对象,或者重用session,但请确保在查询之后创建它

这种影响是由MySQL的一些默认策略造成的

如果您使用InnoDB作为MySQL的默认存储引擎,那么它将用作其隔离级别。这是默认设置,因为在大多数情况下,避免内部事务是有意义的。 因此,如果不结束事务,每次都会从数据库中得到相同的结果

从:

当会话用于与数据库对话时,它会在开始通信时立即开始数据库事务。假设autocommit标志保留为其建议的默认值False,则在回滚、提交或关闭会话之前,此事务仍在进行中。如果会话在前一个事务结束后再次使用,则会话将开始一个新事务;由此可知,会话能够跨越多个事务,尽管一次只有一个事务。我们将这两个概念称为事务范围会话范围


另一个不推荐的选项是创建会话,该会话将在每次查询语句之后自动提交事务。

“此外,您应该将会话视为每个请求的事情,而不是整个应用程序中的持久实体。”->我建议在这里使用SQLAlchemy的
作用域_会话
,它会自动考虑线程安全,即为每个线程/请求设置单独的会话,请参阅。
@sched.cron_schedule(second='*/5')
def some_decorated_task():
    date_now = datetime.datetime.now().date()
    for item in DBsession.query(user_groups_n_hosts).filter(user_groups_n_hosts.end_time < str(date_now)): 
        print item.id, item.server_users.native_linux_user
@sched.cron_schedule(second='*/5')
def some_decorated_task():
    date_now = datetime.datetime.now().date()
    sess = Session()
    for item in sess.query(user_groups_n_hosts).filter(user_groups_n_hosts.end_time < str(date_now)): 
        print item.id, item.server_users.native_linux_user
    sess.close()