Python 在使用“经理”时如何使用“经理”;“繁殖”;
这里有一些我正在做的伪代码Python 在使用“经理”时如何使用“经理”;“繁殖”;,python,multiprocessing,Python,Multiprocessing,这里有一些我正在做的伪代码 将多处理导入为mp 从多处理导入管理器 从TQM导入TQM def循环(arg): #做事 # ... results.append(result\u of_stuff) 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': 经理=经理() 结果=manager.list() 使用mp.get_context('spawn')。池(4)作为池: 列表(tqdm(pool.imap(loop,ls),total=len(ls))) #做
将多处理导入为mp
从多处理导入管理器
从TQM导入TQM
def循环(arg):
#做事
# ...
results.append(result\u of_stuff)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
经理=经理()
结果=manager.list()
使用mp.get_context('spawn')。池(4)作为池:
列表(tqdm(pool.imap(loop,ls),total=len(ls)))
#做一些有结果的事情`
# ...
所以这里的问题是循环
不知道结果
。我有一个可行的方法,就是用“fork”代替“spawn”。但是我需要使用“spawn”的原因超出了我的问题范围
那么,我需要做什么最小的更改才能使其正常工作?我真的想保留tqdm
,因此使用imap
PS:我在Linux上您可以使用它添加额外的参数:
import multiprocessing as mp
import os
from functools import partial
from multiprocessing import Manager
from tqdm import tqdm
def loop(results, arg):
results.append(len(arg))
def main():
ctx = mp.get_context("spawn")
manager = Manager()
l = manager.list()
partial_loop = partial(loop, l)
ls = os.listdir("/tmp")
with ctx.Pool() as pool:
results = list(tqdm(pool.imap(partial_loop, ls), total=len(ls)))
print(f"Sum: {sum(l)}")
if __name__ == "__main__":
main()
这种方法会产生一些开销,因为它会产生一个子进程来托管Manager服务器
由于您将在主流程中处理结果,因此我会这样做(但这当然取决于您的情况):
您可以使用添加额外的参数:
import multiprocessing as mp
import os
from functools import partial
from multiprocessing import Manager
from tqdm import tqdm
def loop(results, arg):
results.append(len(arg))
def main():
ctx = mp.get_context("spawn")
manager = Manager()
l = manager.list()
partial_loop = partial(loop, l)
ls = os.listdir("/tmp")
with ctx.Pool() as pool:
results = list(tqdm(pool.imap(partial_loop, ls), total=len(ls)))
print(f"Sum: {sum(l)}")
if __name__ == "__main__":
main()
这种方法会产生一些开销,因为它会产生一个子进程来托管Manager服务器
由于您将在主流程中处理结果,因此我会这样做(但这当然取决于您的情况):
我知道你已经接受了答案,但让我加上我的“两分钱”: 解决问题的另一种方法是使用全局变量
results
初始化池中的每个进程。问题是,当使用spawn
时,新创建的进程不会继承主进程的地址空间(其中包括结果的定义)。相反,执行从程序的顶部开始。但是创建results
的代码永远不会执行,因为if\uuuuuu name\uuuuu='\uuuuu main\uuuu'
检查。但这是一件好事,因为无论如何,您都不需要此列表的单独实例
那么,我们如何在所有流程中共享全局变量结果的相同实例呢?这是通过使用池初始值设定项实现的,如下所示。此外,如果您想要一个准确的进度条,您应该真正使用imap\u unordered
而不是imap
,以便进度条按照任务完成顺序而不是按照任务提交的顺序进行更新。例如,如果提交的第一个任务恰好是最后一个要完成的任务,那么使用imap
将导致进度条在所有任务完成之前不会继续,然后它将一次命中100%
但请注意:imap_unordered
的doumentation仅说明结果将以任意顺序返回,而不是以完成顺序返回。但是,当使用chunksize参数1时(如果未明确指定,则为默认值),结果将按完成顺序返回。如果您不想依赖于此,请改用apply\u async
指定一个将更新progrss栏的回调函数。请参见最后一个代码示例
将多处理导入为mp
从多处理导入管理器
从TQM导入TQM
def初始_池(_结果):
全球成果
结果=_结果
def循环(arg):
导入时间
#做事
# ...
时间。睡眠(1)
结果。追加(arg**2)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
经理=经理()
结果=manager.list()
ls=列表(范围(1,10))
使用mp.get_context('spawn').Pool(4,initializer=init_Pool,initargs=(results,))作为池:
列表(tqdm(pool.imap_无序(循环,ls),总计=len(ls)))
打印(结果)
更新:另一种(更好)方式
将多处理导入为mp
从TQM导入TQM
def循环(arg):
导入时间
#做事
# ...
时间。睡眠(1)
返回参数**2
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
结果=[]
ls=列表(范围(1,10))
使用mp.get_context('spawn')。池(4)作为池:
以tqdm(总=len(ls))作为pbar:
对于池中的v。imap_无序(循环,ls):
结果.追加(五)
pbar.update(1)
打印(结果)
更新:最安全的方式
将多处理导入为mp
从TQM导入TQM
def循环(arg):
导入时间
#做事
# ...
时间。睡眠(1)
返回参数**2
def my_回调(v):
结果.追加(五)
pbar.update(1)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
结果=[]
ls=列表(范围(1,10))
使用mp.get_context('spawn')。池(4)作为池:
以tqdm(总=len(ls))作为pbar:
对于ls中的arg:
apply_async(循环,args=(arg,),callback=(my_callback))
pool.close()
pool.join()
打印(结果)
我知道你已经接受了答案,但让我加上我的“两分钱”:
解决问题的另一种方法是使用全局变量results
初始化池中的每个进程。问题是,当使用spawn
时,新创建的进程不会继承主进程的地址空间(其中包括结果的定义)。相反,执行从程序的顶部开始。但是创建results
的代码永远不会执行,因为if\uuuuuu name\uuuuu='\uuuuu main\uuuu'
检查。但这是一件好事,因为无论如何,您都不需要此列表的单独实例
那么,我们如何在所有流程中共享全局变量结果的相同实例呢?这是通过使用池初始值设定项实现的,如下所示。此外,如果您想要一个准确的进度条,您应该真正使用imap\u unordered
而不是imap
,这样进度条将按任务完成顺序而不是按任务完成顺序更新