【发布时间】:2023-03-12 18:05:01
【问题描述】:
在 Linux 中,我理解每当您派生子进程时,子进程都会获得父进程地址空间的副本。
我不明白为什么这总是可取的。父进程可能具有不应在父进程和子进程之间共享的全局对象不。为什么我们希望子进程始终获取它们?
例如,假设父进程维护一个全局数据库客户端。
client.py
client = None
def get_client():
global client
if client is None:
client = make_new_db_client()
return client
这在我的单进程应用程序中运行良好。但是一旦我开始使用多处理就可能会中断。
问题是我正在跨进程共享db_client 对象。这个数据库代码实际上是一个 3rd 方库。让我们假装它根本不能跨多进程工作。所以,我在父进程中创建了一个db_client,并强制子进程使用它。会失败的。
我认为正确的做法是允许用户有选择地选择跨多进程共享的内容。所以在这种情况下,我根本不会共享 db_client。子进程将启动并创建自己的数据库连接。一切都会好起来的。
但这不是 Python 的设计方式。全局变量总是被复制(至少在 Linux 中)。为什么这样做是可取的?这似乎有时很好,但并非总是如此。
或者是否已经有一种方法可以选择性地对子进程隐藏变量?
【问题讨论】:
-
这是一个非常广泛的问题,与 Python 无关。它是关于进程如何在大多数现代操作系统上工作的。有很多方法可以控制这一点,例如在创建其他变量之前/之后分叉,或者使用管道等 IPC 机制在进程之间进行通信。这完全取决于您的应用程序,但是由于您正在编写它,因此您大概可以选择适合您需求的东西。那是什么?
-
@bnaecker - 感谢您的评论。是的,这是一个相当广泛的问题。至于我的需求,我从一个进行数据库查询的应用程序开始。多进程元素是当我想使用 concurrent.futures.executor 来获得更好的性能时。我不知道执行程序是先运行还是我的主进程先运行。这用于我的研究环境,因此对事件的顺序没有严格的要求。我只想让执行者成为我的主流程的延伸。
-
您的应用程序主要是在查询数据库?除非您正在执行 大量 查询,否则添加更多线程或进程不太可能有所帮助。这是教科书式的 IO-bound 工作,应用程序将主要等待这些请求完成。但是,如果您确实想要并行化工作,那么从完全独立的进程开始通常是一个好主意,这些进程在需要时通信,而不是共享状态。
multiprocessing模块提供了许多用于在进程之间发送数据的工具。
标签: python linux multiprocessing python-multiprocessing