Python多进程 - Pool

文章目录

    • 创建进程池
    • 提交任务
      • apply
      • apply_async
      • map
      • map_async
      • imap
      • imap_unordered
      • starmap
      • starmap_async
    • 关闭/终止/等待
      • close
      • terminate
      • join
    • AsyncResult 对象
      • get
      • wait
      • ready
      • successful

创建进程池

from multiprocessing import Pool

num_process = 4

# 创建 num_process 个进程,processes 默认值为 os.cpu_count()
with Pool(processes=num_process) as pool:
    # use pool . . .

提交任务

apply

pool.apply(func[, args[, kwds]])
  • 使用参数 args 和 kwds 调用 func ,其中,args 为一个元组,kwds 为一个字典(以参数名为键)。

  • 它将阻塞调用进程直至 func 执行完成。

  • func 占用进程池中的一个进程。

  • 如,

    from multiprocessing import Pool
    import time
    
    def f(msg, sec):
        time.sleep(sec)
        print(msg)
        
    
    with Pool(processes=1) as pool:
        pool.apply(f, ('In another process', ), {'sec': 3})
        print('main')
    

    结果:

    # 等待 3 秒 ...
    In another process
    main
    

apply_async

pool.apply_async(func[, args[, kwds[, callback[, error_callback]]]])
  • pool.apply 的异步版本。

  • 调用它时,它立即返回一个 AsyncResult 对象。

  • 当 func 成功执行完成时,它使用就绪的结果调用 callback 回调;

    当 func 执行出错时,它使用相应的异常实例调用 error_callback 回调。

    处理回调函数的相关线程将阻塞,直至回调函数执行完毕。

  • 如,

    from multiprocessing import Pool
    import time
    
    def f(x, sec, success=True):
        print('x = ', x)
        time.sleep(sec)
        if success:
            return x * x
        return x / 0
        
    def callback(result):
        print('execute f successfully!')
        print(result)
    
    def error_callback(error):
        print('execute f failed!')
        print(error)
    
    with Pool(processes=2) as pool:
        pool.apply_async(f, (3, 3), {'success': True}, callback, error_callback)
        pool.apply_async(f, (4, 3), {'success': False}, callback, error_callback)
        print('main')
        time.sleep(4)
    

    结果:

    from multiprocessing import Pool
    import time
    
    def f(x, sec, success=True):
        print('x = ', x)
        time.sleep(sec)
        if success:
            return x * x
        return x / 0
        
    def callback(result):
        print('execute f successfully!')
        print(result)
    
    def error_callback(error):
        print('execute f failed!')
        print(error)
    
    with Pool(processes=3) as pool:
        result = pool.apply_async(f, (2, 3), {'success': True}, callback, error_callback)
        pool.apply_async(f, (3, 3), {'success': True}, callback, error_callback)
        pool.apply_async(f, (4, 3), {'success': False}, callback, error_callback)
        
        print(result.get())
        print('main')
        time.sleep(4)				# 等待其他进程完成
    

    结果:

    x =  2
    x =  3
    x =  4
    execute f successfully!
    4
    execute f successfully!
    9
    4
    main
    execute f failed!
    division by zero
    

map

pool.map(func, iterable[, chunksize])
  • 使用可迭代对象 iterable 的每一个元素调用 func 。

  • 它将阻塞调用进程,直至 func 执行完成。

  • 它将 iterable 划分成一系列的块,然后将这些块当作独立的任务提交到进程池;

    分块大小可以通过 chunksize 参数指定,其默认值为 1 。

  • 当 iterable 较长时,此方法比较耗内存,可以使用 pool.imap / pool.imap_unordered 。

  • 如,

    def f(x):
        return x * x
    
    with Pool(processes=2) as pool:
        L = range(1, 20)
        L2 = pool.map(f, L, 5)
        print(L2)
    

    结果:

    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361]
    

map_async

pool.map_async(func, iterable[, chunksize[, callback[, error_callback]]])
  • pool.map 的异步版本。

  • 调用它时,它立即返回一个 AsyncResult 对象。

  • 当 func 成功执行完成时,它使用就绪的结果值调用 callback 回调;

    当 func 执行出错时,它使用相应的异常实例调用 error_callback 回调。

    处理回调函数的相关线程将阻塞,直至回调函数执行完毕。

  • 如,

    def f1(x):
        return x * x
        
    def f2(x):
        return x / 0
    
    def callback(result):
        print('execute f successfully!')
        print(result)
    
    def error_callback(error):
        print('execute f failed!')
        print(error)
    
    with Pool(processes=4) as pool:
        L = range(1, 21)
        L1 = pool.map_async(f1, L)
        pool.map_async(f1, L, 2, callback, error_callback)
        pool.map_async(f2, L, 2, callback, error_callback)
    
        print(L1.get())
        print('main')
        time.sleep(4)
    

    结果:

    execute f successfully!
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400]
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400]
    main
    execute f failed!
    division by zero
    

imap

pool.imap(func, iterable[, chunksize])
  • pool.map 的懒惰版本,返回值为一个生成器。

  • 当 iterable 较长时,使用较大的 chunksize 会比较快。

  • 如,

    def f(x):
        return x * x
        
    def get_kth_number(g, k):
        for _ in range(k):
            next(g)
        return next(g)
    
    
    with Pool(processes=4) as pool:
        L = range(1, 10000001)
    
        s = time.time()
        L1 = pool.imap(f, L, 100)
        e = time.time()
        print('consume time {}, median {}'.format((e-s), get_kth_number(L1, 5000000)))
    
    
        s = time.time()
        L2 = pool.imap(f, L, 1000)
        e = time.time()
        print('consume time {}, median {}'.format((e-s), get_kth_number(L2, 5000000)))
    
        print('main')
    

    结果:

    consume time 7.724761962890625e-05, median 25000010000001
    consume time 2.1696090698242188e-05, median 25000010000001
    main
    

imap_unordered

pool.imap_unordered(func, iterable[, chunksize])
  • 和 pool.imap 相似,只是返回结果是无序的(当只有一个工作进程时,结果还是有序的)。

  • 如,

    def f(x):
        return x * x
    
    with Pool(processes=2) as pool:
        L = range(1, 21)
    
        L1 = pool.imap_unordered(f, L, 2)
        print(list(L1))
    
        print('main')
    

    结果:

    [9, 16, 1, 4, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400]
    main
    

starmap

pool.starmap(func, iterable[, chunksize])
  • 和 pool.map 相似,只是 iterable 中的每一个元素又是一个可迭代对象,且它们将被 unpacked ,然后作为 func 的参数。

  • 如,

    def f(x, y):
        return x + y
    
    with Pool(processes=2) as pool:
        L = zip(range(1, 21), range(10, 31))
    
        L1 = pool.starmap(f, L, 2)
        print(list(L1))
    
        print('main')
    

    结果:

    [11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49]
    main
    

starmap_async

pool.starmap_async(func, iterable[, chunksize[, callback[, error_callback]]])
  • pool.starmap 的异步版本。

  • 参数解释和 pool.map_async 一致。

  • 如,

    def f1(x, y):
        return x + y
        
    def f2(x, y):
        return x / 0
    
    def callback(result):
        print('execute f successfully!')
        print(list(result))
    
    def error_callback(error):
        print('execute f failed!')
        print(error)
    
    with Pool(processes=4) as pool:
        g1 = zip(range(1, 21), range(10, 31))
        g2 = zip(range(1, 21), range(10, 31))
        g3 = zip(range(1, 21), range(10, 31))
    
        L1 = pool.starmap_async(f1, g1)
        pool.starmap_async(f1, g2, 1, callback, error_callback)
        pool.starmap_async(f2, g3, 1, callback, error_callback)
    
        print(L1.get())
        print('main')
        time.sleep(4)
    

    结果:

    execute f successfully!
    [11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49]
    [11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49]
    main
    execute f failed!
    division by zero
    

关闭/终止/等待

close

pool.close()
  • 阻止继续提交任务。
  • 当所有任务都完成时,工作进程将终止。

terminate

pool.terminate()
  • 立即停止工作进程,不必等待任务完成。

join

pool.join()
  • 等待所有的工作进程退出。
  • 必须在调用 join 之前调用 close 或 terminate 。

AsyncResult 对象

Pool.apply_async() 、 Pool.map_async() 及 Pool.starmap_async() 的返回值。

get

result.get([timeout])
  • 就绪时,返回结果。
  • 当 timeout 不为 None 时,最多等待 timeout 秒,超时时抛出 multiprocessing.TimeoutError 。

wait

result.wait([timeout])
  • 等待直至结果就绪,或最多等待 timeout 秒。

ready

result.ready()
  • 测试调用是否已完成。

successful

result.successful()
  • 测试调用是否已成功完成。
  • 如果结果未就绪,则抛出 AssertionError 。

你可能感兴趣的:(Python)