UserWarning: MongoClient 在 fork 之前打开。仅在 fork 后创建 MongoClient
Posted
技术标签:
【中文标题】UserWarning: MongoClient 在 fork 之前打开。仅在 fork 后创建 MongoClient【英文标题】:UserWarning: MongoClient opened before fork. Create MongoClient only after forking 【发布时间】:2021-03-23 03:08:01 【问题描述】:我在一个项目中使用mongoengine
,我需要从multiprocessing
库中生成各种Process
对象。主进程使用数据库来确定需要做什么,然后生成一个新的Process
来处理它。每个Process
都需要访问数据库以获取自己的数据。我更喜欢使用Process
对象来保留
我已经对其进行了结构化,以便每个进程在启动时调用mongoengine.connect(name, host=host, port=port)
,但我仍然收到警告:
UserWarning: MongoClient opened before fork. Create MongoClient only after forking
警告意味着在生成新的Process
之前我无法打开 MongoClient。我还没有遇到任何不利影响,但我宁愿拥有一个强大的应用程序。
我想要一种模式,我可以将其应用于类似的问题:
import mongoengine
from multiprocessing import Process
mongoengine.connect(dbname, host=host, port=port)
def worker_process()
mongoengine.connect(dbname, host=host, port=port)
# Fetch lots of web data via bs4
# do some work with the DB
mongoengine.disconnect()
# do some work with the DB
process = Process(worker_process)
process.start()
# do some work with the DB
process.join()
这大大简化了我正在做的事情(检查它何时应该产生许多进程的无休止循环)
我读过关于在连接参数中添加connect=False
,但据我所知,它只会使套接字连接变得懒惰,如果我在创建新的Process
之前开始使用数据库,它将仍然有同样的问题。
我还考虑过在每个 Process
中创建一个唯一别名(我可以只使用 PID 作为别名),但我似乎找不到告诉该进程使用该别名的方法。
我有两个不得已的办法:
移动到线程并失去杀死线程的能力。此外,我对 Threading 的问题也不太熟悉。流程对我的目的一直很有用,并且让我印象深刻得多。我知道它们更重,但我不关心整体性能,更健壮。也许有人可以用“如果你只是......你不必担心线程”来说服我
创建一个专用的Process
来使用数据库并确定要做什么,它会将任务报告回主进程以生成新的Process
对象。因此主进程永远不会有mongoengine
实例。如果没有必要,我真的不想走这条路,因为这将是一次重大的重组。
【问题讨论】:
【参考方案1】:永不失败。做一大堆研究,一无所获。提出问题,接下来您就会知道答案就在您手中。
原来我的 docker 容器有问题,但我的桌面没有。我使用 MacOS 进行开发,在多处理库中偶然发现了这个脚注:
在 3.8 版中更改:在 macOS 上,spawn start 方法现在是 默认。分叉启动方法应该被认为是不安全的,因为它可以 导致子进程崩溃。请参阅 bpo-33725。
所以我在 3.8 上测试/验证并使用 spawn
方法,我什至没有意识到这一点。我刚刚添加了一行强制spawn
在启动时:
import multiprocessing as mp
# bla bla bla
if __name__ == '__main__':
mp.set_start_method('spawn')
一切都开始工作了。
故事的寓意,如果有人想将 MongoEngine/pyMongo 与多处理库一起使用,请确保将启动方法设置为 spawn
。在创建流程时会花费一些性能,但在这种情况下会创建更强大的分离。
【讨论】:
以上是关于UserWarning: MongoClient 在 fork 之前打开。仅在 fork 后创建 MongoClient的主要内容,如果未能解决你的问题,请参考以下文章
kde plot : UserWarning: Dataset has 0 variance;跳跃密度估计
matplotlib显示中文(解决UserWarning: findfont: Font family)
如何在屏蔽数据后避免由 python 使用 UserWarning 完成的隐式修复
UserWarning: Label not :NUMBER: is present in all training examples