python---twisted的使用

twisted的网络使用

twisted的异步使用

一:简单使用

from twisted.internet import defer
from twisted.web.client import getPage
from twisted.internet import reactor

def one_done(arg):
    print(arg)

def all_done(arg):
    print("all done")
    reactor.stop()

@defer.inlineCallbacks
def task(url):
    res = getPage(bytes(url,encoding="utf-8"))  #获取页面,发送http请求,是使用select池将所有socket请求保存,依据此进行计数。
    print('6',type(res))    #<class 'twisted.internet.defer.Deferred'>
    res.addCallback(one_done)   #对每一个请求都添加一个回调方法
    yield res   #返回他

start_url_list = [
    'http://www.baidu.com',
    'http://www.github.com',
]

defer_list = []
for url in start_url_list:
    v = task(url)   #发送请求后立即返回,不等待返回,v是一个特殊对象,标志你发送到那个请求
    print(v,type(v))
    defer_list.append(v)

d = defer.DeferredList(defer_list)  #将上面的特殊对象列表一起放入DeferredList
d.addBoth(all_done)  #为所有对象添加回调

reactor.run()  #会一直循环,我们需要在任务执行完毕后关闭。含有计数器,执行一个任务,会执行一次one_done,计数减一。单任务执行完毕,计数为0,执行all_done

二:模块了解,getPage创建连接,放入select池中,进行计数,在事件循环时依据计数进行关闭(所以执行后自动关闭)

from twisted.internet import defer
from twisted.web.client import getPage
from twisted.internet import reactor

def one_done(arg):
    print(arg)

def all_done(arg):
    print("all done")
    reactor.stop()

@defer.inlineCallbacks
def task(url):
    res = getPage(bytes(url,encoding="utf-8"))  #获取页面,发送http请求,创建socket
    res.addCallback(one_done)   #对每一个请求都添加一个回调方法
    yield res   #返回他

    res = getPage(bytes(url,encoding="utf-8"))  #获取页面,发送http请求
    res.addCallback(one_done)   #对每一个请求都添加一个回调方法
    yield res   #返回他


start_url_list = [
    'http://www.baidu.com',
    'http://cn.bing.com',
]

defer_list = []
for url in start_url_list:
    v = task(url)   #发送请求后立即返回,不等待返回,v是一个特殊对象,标志你发送到那个请求
    print(v,type(v))
    defer_list.append(v)

d = defer.DeferredList(defer_list)  #将上面的特殊对象列表一起放入DeferredList
d.addBoth(all_done)#为所有对象添加回调

reactor.run()#会一直循环,我们需要在任务执行完毕后关闭。含有计数器,执行一个任务,会执行一次one_done,计数减一。单任务执行完毕,计数为0,执行all_done

 

三:Deferred创建一个特殊socket对象,不放人select池,不发送请求,需要我们自己去终止

# coding:utf8
# __author:  Administrator
# date:      2018/6/28 0028
# /usr/bin/env python
from twisted.internet import defer
from twisted.web.client import getPage
from twisted.internet import reactor


def one_done(arg):
    print(arg)


def all_done(arg):
    print("all done")
    reactor.stop()


@defer.inlineCallbacks
def task():
    url = "http://www.baidu.com"
    res = getPage(bytes(url, encoding="utf-8"))  # 获取页面,发送http请求
    res.addCallback(one_done)  # 对每一个请求都添加一个回调方法

    url = "http://cn.bing.com"
    res = getPage(bytes(url, encoding="utf-8"))  # 获取页面,发送http请求
    res.addCallback(one_done)  # 对每一个请求都添加一个回调方法

    url = "http://www.cctv.com"
    res = getPage(bytes(url, encoding="utf-8"))  # 获取页面,发送http请求
    res.addCallback(one_done)  # 对每一个请求都添加一个回调方法

    yield defer.Deferred()


defer_list = []
v = task()  # 发送请求后立即返回,不等待返回,v是一个特殊对象,标志你发送到那个请求
defer_list.append(v)

d = defer.DeferredList(defer_list)  # 将上面的特殊对象列表一起放入DeferredList
d.addBoth(all_done)  # 为所有对象添加回调

reactor.run()  # 会一直循环,我们需要在任务执行完毕后关闭。含有计数器,执行一个任务,会执行一次one_done,计数减一。单任务执行完毕,计数为0,执行all_done

 注意:

 会执行每个getPage的回调 ,不会执行所有请求的公共回调,所有可以在每个的回调中进行处理,让他(将他设为全局)暂停。

count = 0
_close = None

def one_done(arg):
    print(arg)
    global count
    count += 1
    if count == 3:  #callback(None)会停止Deferred对象
        _close.callback(None)  #可以知道获取的响应数据是在事件循环中才去read,task方法只是创建写入socket

def all_done(arg):
    print("all done")
    reactor.stop()


@defer.inlineCallbacks  #协程预激活器,在装饰器内部先使用send(None)激活协程
def task():
    url = "http://www.baidu.com"
    res = getPage(bytes(url, encoding="utf-8"))  # 获取页面,发送http请求
    res.addCallback(one_done)  # 对每一个请求都添加一个回调方法

    url = "http://cn.bing.com"
    res = getPage(bytes(url, encoding="utf-8"))  # 获取页面,发送http请求
    res.addCallback(one_done)  # 对每一个请求都添加一个回调方法

    url = "http://www.cctv.com"
    res = getPage(bytes(url, encoding="utf-8"))  # 获取页面,发送http请求
    res.addCallback(one_done)  # 对每一个请求都添加一个回调方法

    global _close
    _close = defer.Deferred()
    yield _close


defer_list = []
v = task()  # 发送请求后立即返回,不等待返回,v是一个特殊对象,标志你发送到那个请求
defer_list.append(v)

d = defer.DeferredList(defer_list)  # 将上面的特殊对象列表一起放入DeferredList
d.addBoth(all_done)  # 为所有对象添加回调

reactor.run()  # 会一直循环,我们需要在任务执行完毕后关闭。含有计数器,执行一个任务,会执行一次one_done,计数减一。单任务执行完毕,计数为0,执行all_done

四:简单模拟一次请求

from twisted.internet import defer
from twisted.internet.defer import Deferred

_close = None

def one_done(arg):
print(arg)
_close.callback(None)  #将Deferred对象停止,之后才会去执行all_done,在all_done中终止掉事件循环

def all_done(arg):
print("all done")
reactor.stop()

def coro_active(func):
def inner(*args,**kwargs):
gen = func(*args,**kwargs)
deferred = Deferred()
global _close
_close = deferred
result = gen.send(None) #预激活完成,执行到yield res

if isinstance(result, Deferred):
# a deferred was yielded, get the result.
return deferred #返回一个特殊socket对象,不会发送请求,阻塞在这,在事件循环中,会被自动停止
return inner

@coro_active  #协程预激活器
def task():
url = "http://www.baidu.com"
res = getPage(bytes(url, encoding="utf-8")) # 获取页面,发送http请求
#内部对getPage的deferred进行了计数(是使用了队列),当运行一个getPage就会减一self._cancellations-=1,当为0时会退出循环,但是当我们自己返回一个deferred对象,则该对象计数不会自动去销毁,导致一直处于IO循环
res.addCallback(one_done) # 对每一个请求都添加一个回调方法

yield res


defer_list = []
v = task() # 发送请求后立即返回,不等待返回,v是一个特殊对象,标志你发送到那个请求
print(v)
defer_list.append(v)

d = defer.DeferredList(defer_list) # 将上面的特殊对象列表一起放入DeferredList
d.addBoth(all_done) # 为所有对象添加回调

reactor.run()

注意:在上面正常使中yield getPage(...),@defer.inlineCallbacks预激活器也是返回了一个Deferred对象,他是否在预激活器中使用了一样的方法。

五:Scrapy模拟

from twisted.internet import defer
from twisted.web.client import getPage
from twisted.internet import reactor

count = 0
_close = None

def one_done(arg):
    print(arg)
    global count
    count += 1
    if count == 6:
        _close.callback(None)
        pass



def all_done(arg):
    print("all done")
    reactor.stop()

@defer.inlineCallbacks
def task(): #一个task相当于一个爬虫
    #看做是递归的
    #第一个是start_url
    url = "http://www.baidu.com"
    res = getPage(bytes(url, encoding="utf-8"))  # 获取页面,发送http请求
    res.addCallback(one_done)  # 对每一个请求都添加一个回调方法

    #下面两个可以看做parse中yield Request获取的请求
    url = "http://cn.bing.com"
    res = getPage(bytes(url, encoding="utf-8"))  # 获取页面,发送http请求
    res.addCallback(one_done)  # 对每一个请求都添加一个回调方法

    url = "http://www.cctv.com"
    res = getPage(bytes(url, encoding="utf-8"))  # 获取页面,发送http请求
    res.addCallback(one_done)  # 对每一个请求都添加一个回调方法

    #若是任务没有结束,Deferred对象就一直hold住事件循环,当任务结束,事件循环停止
    global _close
    if not _close:
        _close = defer.Deferred()
    yield _close


spider1 = task()
spider2 = task()
#两个爬虫都是并发的,内部请求也是并发的

d = defer.DeferredList([spider1,spider2])  # 将上面的特殊对象列表一起放入DeferredList
d.addBoth(all_done)  # 为所有对象添加回调

reactor.run()  # 会一直循环,我们需要在任务执行完毕后关闭。含有计数器,执行一个任务,会执行一次one_done,计数减一。单任务执行完毕,计数为0,执行all_done

猜你喜欢

转载自www.cnblogs.com/ssyfj/p/9242890.html