繁体   English   中英

我要么不了解 Python 或 Flask+SQLAlchemy 中的多处理

[英]I either don't understand multiprocessing in Python or Flask+SQLAlchemy

前段时间,我在 Python 3 中编写了一个 Flask 应用程序,它产生了一个新线程来进行一些处理,然后定期更新应用程序数据库(SQLite)。 我用来更新数据库的 function 非常简单:

def update_db(tsid, **kwargs):
    # FLASK_APP is my main Flask() object, set once when thread starts
    # DATABASE is the SQLAlchemy DB connection, set once when thread starts
    # TrainingSession is my custom DB model object (from SQLAlchemy.Model)
    with FLASK_APP.app_context():
        dbrec = TrainingSession.query.filter_by(id=tsid).first()
        if dbrec:
            for key, value in kwargs.items():
                setattr(dbrec, key, value)
            DATABASE.session.commit()

这工作得很好 - 我的线程已经产生了几个其他线程,每个线程都调用上面的update_db() function,它正确地更新了数据库。

现在我改变了我的代码,因为我想使用一个进程而不是一个线程(然后它会再次产生其他线程)。 所以我只是简单地从 Python multiprocessing.Process而不是threading.Thread继承我的 class 。 这个子进程现在完成了所有的工作——而且仍然正确。

很好。 但是我不明白为什么我的数据库更新仍然像以前一样工作,即使我没有改变上面显示的逻辑。 全局变量FLASK_APPDATABASE在我的主应用程序进程中设置,在新进程启动之前。 然后在这个新过程中,我仍然像上面一样调用全局 function update_db() ,这仍然有效。

首先,另一个进程如何访问这两个全局变量? 它们不会从主进程传递到子进程,后者只是简单地访问它们而无需更改任何代码(因为它们是 Python 脚本中的全局对象)。 此外,如果FLASK_APPDATABASE对象都已在主进程中创建(并且,再一次,从未传递给子进程),子进程如何访问和更新数据库?

这是因为默认情况下多处理使用fork()创建新进程,这意味着整个 memory state 包括父级中的所有这些变量也存在于子级中。

如果您将多处理更改为spawn模式,您将获得没有任何现有 state 的新解释器,并且您的代码将不再神奇地工作。

文档在https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods进行了解释

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM