def handle_spider_output(self, result, request, response, spider):
if not result:
return defer_succeed(None)
it = iter_errback(result, self.handle_spider_error, request, response, spider)
dfd = parallel(it, self.concurrent_items,
self._process_spidermw_output, request, response, spider)
return dfd
def iter_errback(iterable, errback, *a, **kw):
"""Wraps an iterable calling an errback if an error is caught while
iterating it.
"""
it = iter(iterable)
while True:
try:
yield next(it)
except StopIteration:
break
except:
errback(failure.Failure(), *a, **kw)

包装一个iter,使其可以在迭代时出现异常时调用 错误处理函数。

def parallel(iterable, count, callable, *args, **named):
"""Execute a callable over the objects in the given iterable, in parallel,
using no more than ``count`` concurrent calls. Taken from: http://jcalderone.livejournal.com/24285.html
"""
coop = task.Cooperator()
work = (callable(elem, *args, **named) for elem in iterable)
return defer.DeferredList([coop.coiterate(work) for _ in range(count)])

并行处理函数,通过twisted的task来实现的。work是一个生成器,每次迭代时,使work前进一步。defer.DeferredList([coop.coiterate(work) for _ in range(count)])生成count个cooperatertask,定时调用work,直到迭代完成。由此可见,蜘蛛输出是一个deferredlist,一个defer在执行callback时,return是defer时,会停止执行callback,等待到结果执行callback时才能再次继续执行。这样实现了defer的串联执行,外层defer相当于总控制,callback返回defer相当于下层的分支。

def coiterate(self, iterator, doneDeferred=None):
"""
Add an iterator to the list of iterators this L{Cooperator} is
currently running. Equivalent to L{cooperate}, but returns a L{defer.Deferred} that will
be fired when the task is done. @param doneDeferred: If specified, this will be the Deferred used as
the completion deferred. It is suggested that you use the default,
which creates a new Deferred for you. @return: a Deferred that will fire when the iterator finishes.
"""
if doneDeferred is None:
doneDeferred = defer.Deferred()
CooperativeTask(iterator, self).whenDone().chainDeferred(doneDeferred)
return doneDeferred

cooperator什么时候调用start开始执行任务?其实在构造cooperator时started=True,所以CooperativeTask()时,会把task加入cooperator,同时调用cooperator的_reschedule()使其可以参与调度。

def _addTask(self, task):
"""
Add a L{CooperativeTask} object to this L{Cooperator}.
"""
if self._stopped:
self._tasks.append(task) # XXX silly, I know, but _completeWith
# does the inverse
task._completeWith(SchedulerStopped(), Failure(SchedulerStopped()))
else:
self._tasks.append(task)
self._reschedule()
def _tick(self):#每次调度时会遍历没有停止的任务,每个任务会执行onework。
"""
Run one scheduler tick.
"""
self._delayedCall = None
for taskObj in self._tasksWhileNotStopped():
taskObj._oneWorkUnit()
self._reschedule() _mustScheduleOnStart = False
def _reschedule(self):
if not self._started:
self._mustScheduleOnStart = True
return
if self._delayedCall is None and self._tasks:
self._delayedCall = self._scheduler(self._tick)延时call为定时调用tick函数。
EPSILON = 0.00000001
def _defaultScheduler(x):
from twisted.internet import reactor
return reactor.callLater(_EPSILON, x)

通过self._scheduler(self._tick)(_defaultScheduler(x))使twisted的reactor能不断调用tick函数。

twisted的task之cooperator和scrapy的parallel()函数的更多相关文章

  1. scrapy item处理----cooperator和parallel()函数

    twisted的task之cooperator和scrapy的parallel()函数 本文是关于下载结果返回后调用item处理的过程实现研究. 从scrapy的结果处理说起 def handle_s ...

  2. 重新想象 Windows 8 Store Apps (43) - 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)

    [源码下载] 重新想象 Windows 8 Store Apps (43) - 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel) 作者:webabcd 介绍重新想象 W ...

  3. scrapy之parallel

    Limiting Parallelism jcalderone May 22nd, 2006 This blog has moved! Read this post and its comments ...

  4. 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)

    Task - 基于线程池的任务(在 System.Threading.Tasks 命名空间下) 多 Task 的并行执行 Parallel - 并行计算(在 System.Threading.Task ...

  5. scrapy yield 回调函数不执行解决方案

    yield Request(url=parse.urljoin(response.url, p_url),callback=self.parse_detail) 回调函数不执行: 加上: dont_f ...

  6. scrapy框架Request函数callback参数为什么是self.parse而不是self.parse( )

    加括号是调用函数,不加括号是指的是函数地址,此处只需要传入函数的地址,等待程序到时调用即可

  7. twisted task.cpperator

    twisted task.cpperator 1.      twisted task.cpperator 1.1.    简介-cooperator 官方文档: https://twistedmat ...

  8. scrapy 源码解析 (三):启动流程源码分析(三) ExecutionEngine执行引擎

    ExecutionEngine执行引擎 上一篇分析了CrawlerProcess和Crawler对象的建立过程,在最终调用CrawlerProcess.start()之前,会首先建立Execution ...

  9. Scrapy 爬虫 使用指南 完全教程

    scrapy note command 全局命令: startproject :在 project_name 文件夹下创建一个名为 project_name 的Scrapy项目. scrapy sta ...

随机推荐

  1. crontab(暂存待完善)

    crontab  -e 编辑 ,(使用默认编辑器) -l  列出 第1列分钟1-59 第2列小时1-23(0表示子夜) 第3列日1-31 第4列月1-12 第5列星期0-6(0表示星期天) 第6列要运 ...

  2. Vue 错误记录:Cannot read property 'beforeRouteEnter' of undefined

    点击某路由链接,页面提示: Cannot read property 'beforeRouteEnter' of undefined 查看代码并无手写beforeRouterEnter设置, 把页面内 ...

  3. 原生JS实现选中的radio变为未选中

    需求如下,radio已经选中,再点击,取消选中状态. 效果如链接:演示地址 直接上代码: <!DOCTYPE html> <html> <head> <met ...

  4. 【代码问题】MatConvNet自带example中 fast_rcnn_evaluate出错

    fast_rcnn_evaluate中调用cnn_setup_data_voc07函数读取相关数据时,在类似 [gtids,t]=textread(sprintf(VOCopts.imgsetpath ...

  5. 【C++】Lambda表达式

    转自 https://www.cnblogs.com/DswCnblog/p/5629165.html 作者:dsw846 C++11的一大亮点就是引入了Lambda表达式.利用Lambda表达式,可 ...

  6. Win10系统下Anaconda下安装多种Python函数库

    建议直接安装Anaconda,这是一个包含Numpy,Pandas,Sklearn等函数库的计算机科学软件包,下面的软件可以在此环境下进行安装下载. 一.计算机视觉 1. OpenCV图像处理 在ht ...

  7. JavaScript 高级特性

    1. 原型Prototype 1.1 构造函数 所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量.对构造函数使用new运算符,就能生成实例,并且this变量会绑定 ...

  8. Windows下安装配置Flutter

    Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面. Flutter可以与现有的代码一起工作.在全世界,Flutter正在被越来越多的开发者和组织使用,并且 ...

  9. select、poll、epoll之间的区别总结[转载]

    转载:https://www.cnblogs.com/Anker/p/3265058.html select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述 ...

  10. 为什么PPIO要设计支付代理节点?

    PPIO是我和姚欣发起的去中心化存储项目(https://pp.io),这是为开发者提供的存储和分发网络平台,使得比云存储更廉价,更高速,更隐私.   我在设计PPIO的时候,设计了一个商业角色——支 ...