背景:串行执行慢,考虑使用多进程来加速。
1 多进程
这块可以参考:https://blog.csdn.net/Hao_ge_666/article/details/120571731
2 多线程
这块可以参考:https://blog.csdn.net/Hao_ge_666/article/details/120603014
3 进程池
当任务需求重,需要并发更多的进程时,每次手动维护多进程则会变得不太方便。python 提供了进程池的相关能力,通过指定一个固定资源量的进程池,在进程池中开启或回收进程,整体管理由进程池维护。
3.1 基础模版
# 实例化一个进程池对象,max_workers 设置进程池中能同时运行的最大进程数目,如果不指定默认为 cpu 的核数
pool = ProcessPoolExecutor(max_workers=3)
# submit是非阻塞方法,提交一个函数到进程池中,返回一个 future 对象
future1 = pool.submit(target_func, param)
# 关闭进程池
pool.shutdown()
# 与全局函数 map 类似, 将启动多个线程,以异步方式立即对 iterable 执行 map 处理
pool.map(func, iterable)
或者采用 with 写法,使用完毕自动回收:
with ProcessPoolExecutor(max_workers=3) as pool:
pool.submit(target_func, param)
3.2 获取进程相关信息的函数
future1.done() # 判断 future 代表的任务是否执行完成
future1.result() # 获取 future 代表的任务结果,该方法为阻塞方法,timeout 参数可以指定最多阻塞多少秒
future1.cancel() # 取消 future 代表的任务,执行中的任务取消不了,返回 bool
future1.add_done_callback(func) # 为 future代表任务注册一个回调函数,任务执行完成之后会自动调用该函数,被调用的函数默认接收一个 feture 对象
as_completed() # 接收一个 future 列表,返回一个生成器,通过迭代能够获取到每一个 future 的结果。
其中 result() 可以获取进程函数的返回结果。
3.3 for 循环多进程任务开启&运行
举个栗子:当我们需要同时验证一批代理 ip 是否可用时,串行的对每个 ip 运行一次检查逻辑显然并不是一个高效的做法,为了加速验证,可以借助进程池,下面是示例代码
from tqdm import tqdm # 一个进度条组件
def check_proxy_icanhazip(ip, port):
print('test func')
return True
all_proxies = [
{'ip':'11.11.11.11', 'port':'111'}, {'ip':'22.22.22.22','port':'222'}
] # 待验证代理
print(f'IP 验证,主进程开始执行, pid:{os.getpid()}')
all_proxies_filter = dict()
# with 方式开启进程池
with ProcessPoolExecutor(max_workers=50) as pool:
# 循环的对每个代理进行验证
for proxy in tqdm(all_proxies, desc='checking proxies...'):
# 向进程池中提交一次验证操作
task = pool.submit(check_proxy_icanhazip, proxy['ip'], proxy['port'])
# 进程执行返回结果(即 check_proxy_icanhazip() 的执行返回结果)
res = task.result()
if res:
all_proxies_filter[proxy['ip']] = proxy
all_proxies_filter = all_proxies_filter.values()
print(all_proxies_filter)
""" 方式2:as_completed() 方式来接收一个 future 列表
# 但是这种方式无法方便的自定义每个进程运行结束的判断逻辑
all_task = [pool.submit(check_proxy_icanhazip, (proxy['ip'], proxy['port'])) for proxy in all_proxies]
for future in as_completed(all_task):
res = future.result()
print(f"res: {res}")
"""
标签:python,ip,future,proxy,进程,proxies,pool
From: https://www.cnblogs.com/zishu/p/17300868.html