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. ACM山东工商 Contest - 软件171-2 第1次测验

    #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node *next ...

  2. 删除排序数组中的重复项-leetcode-26

    public:    int removeDuplicates(vector<int>& nums) {        int size=nums.size();        i ...

  3. sqlserver数据库知识点总结(转)

  4. sqlmap的安装

    来自:http://www.51testing.com/html/89/n-3711589.html 一.下载 首先,需下载SqlMap以及适用于Windows系统的Python.下载地址如下: 1. ...

  5. 存储专栏:一句话说清RAID2.0

     今天,西瓜哥来谈谈高端存储的一股势力,RAID 2.0,最近被华为HVS搞得风生水起,神奇的让人摸不着头脑.我还是从一个高端存储的江湖说起吧. 据说很久很久以前(别扔臭鸡蛋,讲故事都是这样的…),L ...

  6. JIRA的邮件通知

    提交测试或提交上线申请时发送给相关的开发人员.测试人员.运维人员. 使用插件Notification

  7. ajax(读取json数据)

    ajax知识点: 语法:$.ajax(路由,请求方式,返回的数据类型,数据参数,回调函数) url: "路由", type:"",默认get请求(get或pos ...

  8. ARC085E MUL

    https://atcoder.jp/contests/arc085/tasks/arc085_c 题目大意 略 解法 最小割即可. 直接建图有负边,但是因为我们知道最后在割上的边数一定为 \(N\) ...

  9. 前端使用nginx 达到前后分离的开发目的

    前言: 由于现在要开发一套基于python 的日志分析系统,设计到日志收集,分析,可视化输出,所以我使用前后端分离的做法.记录学习的过程: 00x1: 下载配置nginx:在E盘创建Service 目 ...

  10. 【算法习题】数组中任意2个(3个)数的和为sum的组合

    题1.给定一个int数组,一个数sum,求数组中和为sum的任意2个数的组合 @Test public void test_find2() { int[] arr = { -1, 0, 2, 3, 4 ...