python进程池停止_python 中的进程池 -- multiprocessing.pool.Pool

进程池最重要的就是使用了,但需要注意的是,所有下面这些方法都必须由创建进程池的进程调用

applyapply(func, args=None, kwds=None)

同步执行函数 func

示例

import logging

import os

from multiprocessing.pool import Pool

from time import sleep

def f():

logging.info('f %s' % os.getpid())

sleep(1)

if __name__ == '__main__':

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s: %(message)s')

with Pool(4) as pool:

pool.apply(f)

pool.apply(f)

pool.apply(f)

pool.apply(f)

pool.apply(f)

打印出了:2019-06-26 16:25:20,028 - INFO: f 198

2019-06-26 16:25:21,035 - INFO: f 199

2019-06-26 16:25:22,040 - INFO: f 200

2019-06-26 16:25:23,043 - INFO: f 201

2019-06-26 16:25:24,045 - INFO: f 198

可以看到,前4次调用 f 依次使用了进程池中的四个不同的进程,最后一次调用复用了第一个进程,每次调用都等待了 1 秒钟

apply_asyncapply_async(self, func, args=(), kwds={}, callback=None, error_callback=None)

上面的例子中,每次调用都间隔了 1 秒钟,没有实现真正的并发,所以我们需要异步执行所有的调用

apply_async 就是 apply 的异步版本

参数与 apply 大体相同,增加了可选的执行完成后自动调用的回调方法参数

示例

import logging

import os

import time

from multiprocessing.pool import Pool

from time import sleep

def f():

sleep(1)

return '%s finish f_call at %s' % (os.getpid(), time.strftime('%Y-%m-%d %H:%M:%S'))

if __name__ == '__main__':

result = []

with Pool(4) as pool:

result.append(pool.apply_async(f))

result.append(pool.apply_async(f))

result.append(pool.apply_async(f))

result.append(pool.apply_async(f))

result.append(pool.apply_async(f))

for res in result:

logging.info(res.get(timeout=10))

打印出了:2019-06-26 18:26:10,563 - INFO: 7212 finish f_call at 2019-06-26 18:26:10

2019-06-26 18:26:10,563 - INFO: 5440 finish f_call at 2019-06-26 18:26:10

2019-06-26 18:26:10,672 - INFO: 7044 finish f_call at 2019-06-26 18:26:10

2019-06-26 18:26:11,577 - INFO: 7212 finish f_call at 2019-06-26 18:26:11

2019-06-26 18:26:11,577 - INFO: 5440 finish f_call at 2019-06-26 18:26:11

通过异步,我们做到了真正的并发调用

mapmap(func, iterable, chunksize=0)

与 Python 标准库中的 map 方法有着相同的用法和功能,不同的是,进程池中的该方法会将 iterable 参数传入的可迭代对象分成 chunksize 份传递给不同的进程来处理

示例

import logging

import os

from multiprocessing.pool import Pool

from time import sleep

import time

def f(i):

print('%s get %s at %s' % (os.getpid(), i, time.strftime('%Y-%m-%d %H:%M:%S')))

sleep(1)

if __name__ == '__main__':

with Pool(4) as pool:

pool.map(f, range(10))

打印出了:107 get 0 at 2019-06-27 19:50:30

109 get 2 at 2019-06-27 19:50:30

108 get 1 at 2019-06-27 19:50:30

110 get 3 at 2019-06-27 19:50:30

107 get 4 at 2019-06-27 19:50:31

109 get 5 at 2019-06-27 19:50:31

108 get 6 at 2019-06-27 19:50:31

110 get 7 at 2019-06-27 19:50:31

107 get 8 at 2019-06-27 19:50:32

109 get 9 at 2019-06-27 19:50:32

可以看到,进程池中的四个进程在同一时刻实现了并发调用,随后并发等待1秒后进行下一轮并发调用

与 apply 的同步调用相比,性能有了很大幅度的提升了

map_asyncmap_async(func, iterable, chunksize=0, callback=None, error_callback=None)

与 apply_async 类似,map_async 是 map 的异步版本,我们可以通过他返回的对象的阻塞调用 get 方法来获取进程执行后的结果,与 apply_async 不同的是,map_async 会先收集多个进程的运行结果后返回

imapimap(func, iterable, chunksize=0)

有时,我们调用 map 传入的可迭代对象的可迭代次数会非常多,如果通过 map 来进行任务的分配和回收,显然会因为计算量过大而出现过度耗时的情况

此前的文章中,我们介绍过生成器与协程,是否可以借助协程的思想通过迭代器与 next 方法逐步获取结果呢?python 进程池已经考虑到这一情况,并引入了 imap 方法,来返回一个迭代器,通过 next 方法逐步拿到其运行结果

imap 方法与 map 方法在参数上是一模一样的,不同之处仅在于其返回的结果

他返回的结果对象是一个迭代器,可以通过向标准库 next 方法传入该迭代器来迭代结果,也可以调用迭代器本身提供的 next 方法来获取结果,值得一提,迭代器本身提供的 next 方法允许传入一个整数的 timeout 参数作为最大超时

示例

import logging

import os

from multiprocessing.pool import Pool

from time import sleep

import time

def f(i):

sleep(1)

return '%s finsh sleep by %s at %s' % (os.getpid(), i, time.strftime('%Y-%m-%d %H:%M:%S'))

if __name__ == '__main__':

with Pool(4) as pool:

it = pool.imap(f, range(10))

res = next(it)

while res:

print(res)

res = next(it)

打印出了:181 get 0 at 2019-06-27 20:02:13

183 get 2 at 2019-06-27 20:02:13

182 get 1 at 2019-06-27 20:02:13

184 get 3 at 2019-06-27 20:02:13

181 get 4 at 2019-06-27 20:02:14

181 finsh sleep by 0 at 2019-06-27 20:02:14

183 get 5 at 2019-06-27 20:02:14

182 get 6 at 2019-06-27 20:02:14

184 get 7 at 2019-06-27 20:02:14

182 finsh sleep by 1 at 2019-06-27 20:02:14

183 finsh sleep by 2 at 2019-06-27 20:02:14

184 finsh sleep by 3 at 2019-06-27 20:02:14

181 get 8 at 2019-06-27 20:02:15

181 finsh sleep by 4 at 2019-06-27 20:02:15

183 get 9 at 2019-06-27 20:02:15

183 finsh sleep by 5 at 2019-06-27 20:02:15

182 finsh sleep by 6 at 2019-06-27 20:02:15

184 finsh sleep by 7 at 2019-06-27 20:02:15

181 finsh sleep by 8 at 2019-06-27 20:02:16

183 finsh sleep by 9 at 2019-06-27 20:02:16

Traceback (most recent call last):

File "/usr/lib/python3.6/multiprocessing/pool.py", line 720, in next

item = self._items.popleft()

IndexError: pop from an empty deque

During handling of the above exception, another exception occurred:

Traceback (most recent call last):

File "x.py", line 21, in 

res = next(it)

File "/usr/lib/python3.6/multiprocessing/pool.py", line 723, in next

raise StopIteration

StopIteration

我们看到,每一轮调用都是 next 方法触发的,和我们曾经介绍过的一样,最终迭代器的最后一次 next 调用会抛出 StopIteration 异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值