gpt4 book ai didi

python - 如何通过多进程共享(或排除共享)全局变量?

转载 作者:行者123 更新时间:2023-12-03 10:00:16 29 4
gpt4 key购买 nike

在 Linux 中,我理解每当您派生子进程时,子进程都会获得父进程地址空间的副本。
我不明白为什么这总是可取的。父进程可能具有不应在父进程和子进程之间共享的全局对象。为什么我们希望子进程总是得到它们?
例如,假设父进程维护一个全局数据库客户端。
客户端.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 中)。为什么这样做是可取的?这似乎有时很好,但并非总是如此。
或者已经有一种方法可以选择性地隐藏子进程中的变量?

最佳答案

它不一定总是可取的。在许多情况下,它是无关紧要的,在某些情况下令人困惑。许多并行编程错误与发散变量和开发人员假设它们是同步的有关。
可取性与这种设计关系不大。在 Linux(和大多数其他 Unix 变体)中,Python 解释器通过调用系统调用 fork() 创建一个子进程。在C级。这会创建一个(几乎)相同的调用 fork 的进程的副本。有一些进程绑定(bind)的资源,例如计时器,不是由子进程继承的,但变量是。
这是传统的 Unix 创建进程的方式,它有一些好处

  • 实现(对于那些开发过 Python 的人)是由一个经受住时间考验的系统调用提供的。
  • 它很快。其中包含的逻辑很少 - 内存只是复制到另一个位置
  • 子流程是可行的。在您的问题中描述的理论混合和匹配模型中,可以创建一个缺少重要组件的子流程
  • 这提供了一种将数据传递给子进程的快速方法

  • 考虑一个不会执行此操作的子流程。这将是一个白板。默认情况下,一个空核心能够稍后以某种方式从创建它的父级接收可执行代码和参数。
    要使其成为一个可运行且有用的组件,需要做更多的工作。在实现中(您需要考虑每个细节)和执行。传输数据需要进程之间的通信。从理论上讲,将进程状态初始化到您想要的位置可能需要大量工作,例如从数据库中读取配置参数。如果您需要启动数千个子流程,则在每个流程中重复此工作将是 很多慢点。
    当然,在某些情况下,继承全局变量会使您误入歧途。出于这个原因,一些开发人员会避开全局变量。外部进程或服务的连接器需要在子进程中重新创建,如果全局变量代表这些,您的程序可能会变得困惑。
    并行编程需要良好的设计和对细节的高度关注的原因之一正是这一点——没有编程语言可以猜测您的程序想要在子进程中做什么。输入和输出是什么?它是否需要与父进程或其他进程或计算机通信?这是怎么发生的?等等。
    完全有可能并行处理不适合您的任务。在很多情况下,由于应用程序的功能,子流程根本无法帮助您。在某些情况下,可以通过重新设计应用程序来解决明显的多处理相关问题。有时在主进程中处理外部通信并且只将计算等分派(dispatch)给子进程可能是明智的。在另一种情况下,让主程序什么都不做或几乎什么都不做,让每个子进程独立订阅外部资源并直接传递结果可能是理想的。许多服务器端应用程序以这种方式工作。
    为一个几乎没有答案的冗长答案道歉。

    关于python - 如何通过多进程共享(或排除共享)全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64546389/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com