使用gevent的Pool实现异步并发

目标

  • 掌握gevent中Pool基本使用
  • 实现代码的重构,使用gevent来进一步提高效率

1 为什么使用gevent

对于I/O密集型任务,gevent能对性能做很大提升的,协程的创建、调度开销都比线程小的多。

2 通过配置文件设置属性,来判断所使用的异步方式

# 异步方式  thread、coroutine
ASYNC_TYPE = 'coroutine'

3 让gevent的Pool和线程池Pool的接口一致

因此需要单独对gevent的Pool进行一下修改,具体如下: 在scrapy_plus下创建async包,随后创建coroutine.py模块

# scrapy_plus/async/coroutine.py
'''
由于gevent的Pool的没有close方法,也没有异常回调参数
引出需要对gevent的Pool进行一些处理,实现与线程池一样接口,实现线程和协程的无缝转换
'''
from gevent.pool import Pool as BasePool
import gevent.monkey
gevent.monkey.patch_all()    # 打补丁,替换内置的模块


class Pool(BasePool):
    '''协程池
    使得具有close方法
    使得apply_async方法具有和线程池一样的接口
    '''
    def apply_async(self, func, args=None, kwds=None, callback=None, error_callback=None):
        return super().apply_async(func, args=args, kwds=kwds, callback=callback)

    def close(self):
        '''什么都不需要执行'''
        pass

4 在引擎中使用上:

# scrapy_plus/core/engine.py
import time
import importlib
from datetime import datetime

from scrapy_plus.http.request import Request    # 导入Request对象
from scrapy_plus.utils.log import logger    # 导入logger
from scrapy_plus.conf import settings

# 判断使用什么异步模式,改用对应的异步池
if settings.ASYNC_TYPE == 'thread':
    from multiprocessing.dummy import Pool    # 导入线程池对象
elif settings.ASYNC_TYPE == 'coroutine':
    from scrapy_plus.async.coroutine import Pool
else:
    raise Exception("不支持的异步类型:%s, 只能是'thread'或者'coroutine'"%settings.ASYNC_TYPE)

# 注意:
# 由于打patch补丁是为了替换掉socket为非阻塞的
# 而下载器中正好使用了requests模块,如果在这之后导入协程池,会导致requests中使用的socket没有被替换成功
# 从而有可能导致使用出现问题
from .scheduler import Scheduler
from .downloader import Downloader

class Engine(object):
    ......
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值