如何在导入的模块中使用multiprocessing.Pool?

时间:2017-03-04 23:29:11

标签: python multiprocessing python-multiprocessing

我无法在此处实施建议:Applying two functions to two lists simultaneously

我想这是因为模块是由另一个模块导入的,因此我的Windows会产生多个python进程?

我的问题是:如果没有if if __name__ == "__main__":

,我怎么能使用下面的代码
args_m = [(mortality_men, my_agents, graveyard, families, firms, year, agent) for agent in males]
args_f = [(mortality_women, fertility, year, families, my_agents, graveyard, firms, agent) for agent in females]

with mp.Pool(processes=(mp.cpu_count() - 1)) as p:
    p.map_async(process_males, args_m)
    p.map_async(process_females, args_f)

process_malesprocess_females都是功能。 args_m, args_f是迭代器

另外,我不需要退货。代理是需要更新的类实例。

2 个答案:

答案 0 :(得分:5)

您需要保护if __name__ == "__main__"中的多处理代码的原因是您不希望它在子进程中再次运行。这可能发生在Windows上,其中解释器需要重新加载其所有状态,因为没有fork系统调用将复制父进程的地址空间。但是你只需要在代码应该在顶级运行的地方使用它,因为你在主脚本中。这不是保护代码的唯一方法。

在您的具体情况下,我认为您应该将multiprocessing代码放在函数中。这不会在子进程中运行,只要没有其他任何东西在不应该的时候调用该函数。您的主模块可以导入模块,然后调用该函数(可能在if __name__ == "__main__"块内)。

它应该是这样的:

<强> some_module.py:

def process_males(x):
    ...

def process_females(x):
    ...

args_m = [...] # these could be defined inside the function below if that makes more sense
args_f = [...]

def do_stuff():
    with mp.Pool(processes=(mp.cpu_count() - 1)) as p:
        p.map_async(process_males, args_m)
        p.map_async(process_females, args_f)

<强> main.py:

import some_module

if __name__ == "__main__":
    some_module.do_stuff()

在您的真实代码中,您可能希望传递一些参数或从do_stuff获取返回值(也应该给出一个比我在本例中使用的通用名称更具描述性的名称)。

答案 1 :(得分:3)

if __name__ == '__main__':的想法是避免无限的过程产生。

当挑选主脚本中定义的函数时,python必须弄清楚主脚本的哪个部分是函数代码。它基本上会重新运行你的脚本。如果创建Pool的代码位于同一脚本中且未受“if main”保护,则尝试导入该函数时,您将尝试启动另一个Pool尝试启动另一个Pool ...

因此,您应该将函数定义与实际主脚本分开:

from multiprocessing import Pool

# define test functions outside main
# so it can be imported withou launching
# new Pool
def test_func():
    pass

if __name__ == '__main__':
    with Pool(4) as p:
        r = p.apply_async(test_func)
        ... do stuff
        result = r.get()