如何在导入的模块中使用 multiprocessing.Pool?
How to use multiprocessing.Pool in an imported module?
我没能执行这里的建议:。
我猜是因为该模块是由另一个模块导入的,因此我的 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_males
和 process_females
都是函数。
args_m, args_f
是迭代器
此外,我不需要 return 任何东西。代理是 class 个需要更新的实例。
if __name__ == '__main__':
的想法是避免无限进程生成。
当 pickle 主脚本中定义的函数时,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()
您需要在 if __name__ == "__main__"
中保护多处理代码的原因是您不希望它在子进程中再次 运行。这可能发生在 Windows 上,解释器需要重新加载其所有状态,因为没有 fork
系统调用将复制父进程的地址 space。但是你只需要在代码应该在顶层 运行ning 的地方使用它,因为你在主脚本中。这不是保护代码的唯一方法。
在您的具体情况下,我认为您应该将 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
中获取一个 return 值(也应该给它一个比我在这个例子)。
还不能对这个问题发表评论,但我使用的一种解决方法是一些人提到的只是在一个不同于进程生成位置的模块中定义 process_males
等函数。然后导入包含多处理生成的模块。
我没能执行这里的建议:
我猜是因为该模块是由另一个模块导入的,因此我的 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_males
和 process_females
都是函数。
args_m, args_f
是迭代器
此外,我不需要 return 任何东西。代理是 class 个需要更新的实例。
if __name__ == '__main__':
的想法是避免无限进程生成。
当 pickle 主脚本中定义的函数时,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()
您需要在 if __name__ == "__main__"
中保护多处理代码的原因是您不希望它在子进程中再次 运行。这可能发生在 Windows 上,解释器需要重新加载其所有状态,因为没有 fork
系统调用将复制父进程的地址 space。但是你只需要在代码应该在顶层 运行ning 的地方使用它,因为你在主脚本中。这不是保护代码的唯一方法。
在您的具体情况下,我认为您应该将 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
中获取一个 return 值(也应该给它一个比我在这个例子)。
还不能对这个问题发表评论,但我使用的一种解决方法是一些人提到的只是在一个不同于进程生成位置的模块中定义 process_males
等函数。然后导入包含多处理生成的模块。