在主进程和工作进程中导入不同的模块集

Import different sets of modules in main and in worker processes

是否可以在使用多进程模块时让进程导入不同的库?例如:

import multiprocessing as mp
import pprint
import sys
import threading

from Foo import Moo

class Worker(mp.Process):
    def __init__(self):
        print "Worker Init"
        mp.Process.__init__(self)

    def run(self):
        print "Worker Running"
        self._static_method()

    @staticmethod
    def _static_method():
        print "I'm a-static, get it?"

class TouchWorker(threading.Thread):
    def __init__(self):
        super(TouchWorker, self).__init__(name="Touchoo" + " TouchWorker")

    def run(self):
        print "Touchoo Running"

class Parasite(mp.Process):
    def __init__(self):
        print "Parasite Init"
        mp.Process.__init__(self)

    def run(self):
        print "Parasite Running"

class Encapsulator(object):
    def __init__(self):
        workers = []

        for _ in range(4):
            wrk = Worker()
            workers.append(wrk)

        for someWorker in workers:
            someWorker.start()

        par = Parasite()
        par.start()

if __name__ == '__main__':
    enc = Encapsulator()

我只需要 'Worker' 和 'Parasite' 进程中的 'Foo' 模块。是否可以让他们在 运行 时导入该模块?

简单地反转防止进程创建无限循环所需的成语..

# this should look familiar
if not __name__ == "__main__":
     from Foo import Moo

您可能会发现,让您的库加载速度更快更容易,只需在主文件中执行此操作即可避免各种荒谬的范围界定问题。这可以通过在子进程启动后要求单独的 Moo.initialize() 调用来实现,但它需要由每个子进程执行,因为内存不共享。

一个好的一般经验法则是库不应该在导入时做任何实际工作,以便它们可以快速加载。从所述库调用函数或 class 后,就会执行必要的工作。

为了生成子进程,multiprocessing 在 UNIX 中使用 fork() 并在 Windows 中使用具有特殊参数的程序 Windows 调用特殊代码试图模拟相同的行为.

因此,当您的子进程被创建时,它们实际上并没有再次初始化,父进程加载的所有模块也已经为它们加载了。

所以,如果你想导入一个模块:

  • 在 master 中而不是在 worker 中:
    • 不可能,也完全没有必要。你所能做的就是让引用模块的变量以某种方式对工作人员不可见
  • 在 worker(s) 中但不在 master 中:
    • import 它在辅助函数中
      • 导入将在每个 worker 中完成,或者
    • import 它在 master 中
      • 导入一次,在master中,children会自动继承,或者
    • import 它在 master 中,然后 del 结果变量(这样它就不会污染 master 的命名空间),然后 import 再次在 workers 中(这将重用来自 sys.modules)
    • 的现有模块对象