在python 3.8 shared_memory 中, resource_tracker 需要被子进程继承,但是如何实现呢?

In python 3.8 shared_memory the resource_tracker needs to be inherited by subprocesses, but how is that accomplished?

基于此错误报告中的讨论以及相关的 SO 问题:

在子进程中使用 shared_memory 时,需要从父进程继承 resource_tracker。如果不是,那么每个子进程都会错误地获得自己的 resource_tracker.

I don't instantiate a resource_tracker anywhere in my code. What does it mean for a resource_tracker to be inherited? How do I instantiate the resource_tracker in the main process prior to creating the new subprocesses so that the resource_tracker gets inherited by the subprocesses?

When using shared_memory in a subprocess the resource_tracker needs to be inherited from the parent process. If it is not then each subprocess erroneously gets its own resource_tracker.

考虑到 ResourceTrackerSharedMemory 的当前实现,此声明存在很大缺陷。前者是作为一个单独的 python 进程实现的,它通过管道与启动它的进程(即创建共享内存对象的进程)进行通信。资源跟踪器拥有管道的读取端,而创建共享内存对象的进程获得管道的写入端。因此,任何时候启动进程创建一个 SharedMemory 对象,它都会通过管道向资源跟踪器发送一条消息到 register 创建的资源。同样,如果需要删除资源,启动进程将再次使用管道发送 unregister 消息。因此,子进程可以 真正 继承其父进程的资源跟踪器的唯一方法是,如果它使用管道的写入端(它应该有进入)。但是,由于 SharedMemory 的当前实现会创建资源跟踪器,即使进程仅使用已创建的共享内存对象,您的子进程也必须与两个单独的资源跟踪器通信:由其父进程启动的(通过同一个管道),以及在他们第一次实例化 SharedMemory 对象时开始的那个。说完这些,让我们来解决您的问题:

我没有在代码中的任何地方实例化 resource_tracker。 resource_tracker被继承是什么意思?

首先,您没有实例化资源跟踪器;当您第一次实例化 SharedMemory 对象时,会为您实例化一个。目前,您是否正在生产或使用共享内存对象并不重要。始终为实例化共享内存对象的进程创建资源跟踪器。

其次,在当前实现中,继承资源跟踪器确实不是一回事。同样,消费进程不应该担心共享内存对象的生命周期。他们所要担心的就是确保该对象确实存在。他们可以通过处理 FileNotFoundErrorOSError 异常来做到这一点。如果 SharedMemory 的当前实现没有错误,当消耗进程使用资源完成时,他们需要做的就是调用 SharedMemory.close 并继续执行其他操作。

如何在创建新子进程之前在主进程中实例化 resource_tracker,以便子进程继承 resource_tracker?

我认为这里的问题是你的设计被翻转了。您应该让主进程创建共享内存对象并让子进程使用它。使用共享内存对象背后的想法是,您可以让多个单独的进程使用相同的内存块,这反过来会限制并行程序使用的资源量。但是 is doing the reverse. Since shared memory objects are kernel persistent resources, it makes sense to have as few of them as possible. So, if you employ a "one producer, multiple consumers" design, you can have your main process create the shared memory object along with its associated resource tracker, and then you let the child processes consume the memory. In this scenario, you could get some work done in the child processes without having to worry about the resource trackers associated with them. But just make sure that the child processes don't unlink the shared memory object before the parent process gets around to doing it. Better yet, if the fix in the bug report 的实现使得消费进程无需生成资源跟踪器,您可以确信您的主进程将是唯一取消链接共享内存对象的实体。

总而言之,就当前的实现而言,您的子进程不会继承其父进程的资源跟踪器。如果这些子进程最终实际创建了共享内存对象,它们将获得自己的资源跟踪器。但是如果效率是目标,您会希望您的主进程创建共享内存对象,然后您的子进程将使用这些对象。在这种情况下,您的主进程将通过其关联的资源跟踪器负责清理步骤。而且,如果实施了修复,您始终可以安全地假设只有主进程将取消链接资源。