笔记-twisted

1.      简介

Twisted is an event-driven networking engine written in Python and licensed under the open source ​MIT license. Twisted runs on Python 2 and an ever growing subset also works with Python 3.

1.1.    什么是异步

最初始的程序是阻塞型的,就是一句一句执行,如果没有执行完,需要等待/阻塞,无疑,这样的架构在大部分时候会浪费处理能力,是比较低效的。

进程,线程更多的体现为硬件的资源分割和调度;到了单线程内,因为CPU和其它组件/网络的速度差异,仍然会空置大量处理能力。

为了提高线程内的效率,有了协程,但是协程仍不够抽象和高效,对复杂事件来说,代码复杂性很高;

其实协程在本文所讨论的情况下最主要的作用说就是存在大批量类似任务时,优先处理不需要等待其它条件的任务;

更进一步,把事件调度,分发机制抽象一下,独立出来,就是常说的异步+回调,事件驱动了;

1.2.    overview

关键概念理解:

Protocol:定义如何处理消息;

Factory:实际处理的组件,可以理解为是工厂化的Protocol;

reactor:循环体,不停循环,接收事件/信号,分发事件/信号至对应处理类;

Application:更上层的结构体,管理多个service/reactor,最顶层的结构

其它相关概念:

defereeds:异步功能的关键,立即返回一个Deferred对象,它是一个承诺,意思是它所包含的任务一定会有一个结果,在有结果时会调用相应处理函数,如果正常则调用callback,异常则调用errback;当然,callback和errback可以是chain。

endpoints:对server,client更精确的操纵;

transport:对连接的描述及操纵。

上述概念理解后,剩下的细节就可以分步填充到框架里了。

除此之外,还有对数据库的异步支持,enterprice.adbapi

------部件理解------

2.      reactor

参考文档:https://twistedmatrix.com/documents/current/api/twisted.internet.reactor.html

reactor实际是一个抽象,具体使用哪一种reactor依赖于平台,当然,也可以手动显示指定。

reactor类型

IReactorCore    IReactorTime    IReactorProcess

IReactorTCP    IReactorSSL    IReactorUDP

IReactorMulticast    IReactorUNIX    IReactorUNIXDatagram

IReactorFDSet    IReactorThreads    IReactorPluggableResolver

每个reactor都有不同的操作和属性:

以最常用的ireactorcore为例(核心)

常用属性有:

  1. run()
  2. stop()
  3. callWhenRunning(callable, *args, **kw)
  4. running

其它比较重要的还有消息注册和维护,不过一般用不到这么深,了解一下就可以了。

3.      protocol

Protocol描述了如何以异步的方式处理网络中的事件,下面是一些典型的操作:

Method

logPrefix

Return a prefix matching the class name, to identify log messages related to this protocol instance.

Method

dataReceived

Called whenever data is received.

Method

connectionLost

Called when the connection is shut down.

Method

makeConnection

Make a connection to a transport and a server.

Method

connectionMade

Called when a connection is made.

4.      factory

定义一些操作和持久化数据,在体系中可以理解为protocol的实例化。

class FingerFactory(protocol.ServerFactory):
    protocol = FingerProtocol

def getUser(self, user):
        return b"No such user"

5.     
deferred

5.1.   
deferred

# deferred 演示案例1
#
from twisted.internet import defer
from twisted.internet import task
from twisted.internet import reactor

# 耗时操作的外壳函数,返回一个deferred对象
# 完成之后的处理函数,使用task模拟了一个耗时操作
def time_wasted_wrapper(job_id):
    def on_done():
        print('time-wasted
job'
+ str(job_id) + 'done!')
        return job_id

print('begin
time-wasted jon'
+ str(job_id))
    return task.deferLater(reactor,
3, on_done)

# 回调函数
def on_one_job_done(result):
    print('result
plus 1!'
)
    return result + 1

def all_jobs_done(result):
    print(str(result))
    print(reactor.__class__)
    print('all jobs
are done!'
)

reactor.stop()
    time.sleep(1)
    print(reactor.running)

# 模拟添加任务
def install_jobs():
    jobs_list = list()
    for i in range(10):
        job = time_wasted_wrapper(i)
        job.addCallback(on_one_job_done)
        jobs_list.append(job)
    deferred_list =
defer.DeferredList(jobs_list)
   
deferred_list.addCallback(all_jobs_done)

def run_module():
    install_jobs()
    print('all jobs
have started!'
)
    reactor.run()
    print('www')
    print(reactor.running)

if __name__ == '__main__':
    run_module()
    # reactor.run()

5.2.   
defer.inlineCallbacks

下面的代码演示了defer.inlineCallbacks的用法

# defer

# @defer.inlineCallbacks
#
from twisted.internet.defer import inlineCallbacks,
Deferred, returnValue
from twisted.python.failure import Failure
from twisted.internet import reactor, defer

def loadRemoteData(callback):
    import time
    time.sleep(1)
    callback(1)

def loadRemoteData2(callback):
    import time
    time.sleep(1)
    callback(2)

@defer.inlineCallbacks
def getRemoteData():
    d1 = defer.Deferred()
    print('start
execute r1!'
)
    reactor.callInThread(loadRemoteData,
d1.callback)
    r1 = yield d1
    print('r1 =',r1)
    d2 = defer.Deferred()
    print('start
execute r2!'
)
    reactor.callInThread(loadRemoteData2,
d2.callback)
    r2 = yield d2
    print('r2 =', r2)

returnValue(r1 + r2)

def getResult(v):
    print ("result=", v)

if __name__ == '__main__':
    d = getRemoteData()
    d.addCallback(getResult)

reactor.callLater(4,
reactor.stop);
    reactor.run()

6.     
twisted理解-代码版

下面是一个逐步添加功能的twisted代码示例,能方便的理解twisted各个组件的作用及关系。

'''
# 1
基础的事务循环
# 创建了一个循环,没有监听任何端口
from twisted.internet import reactor
reactor.run()
'''


'''
# 2
进一步,声明endpoint,绑定,实现监听1079端口
from twisted.internet import protocol, reactor, endpoints
class FingerProtocol(protocol.Protocol):
    pass

class FingerFactory(protocol.ServerFactory):
    protocol = FingerProtocol

fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
fingerEndpoint.listen(FingerFactory())
reactor.run()
'''


'''
# 3 protocol
丰富一些了,会读取一个输入<user>,并返回信息,然后中断连接
# LineReceiver是一个基本的protocol,它有一些方法,具体可查看api

from twisted.internet import protocol, reactor, endpoints
from twisted.protocols import basic

class FingerProtocol(basic.LineReceiver):
    def lineReceived(self, user):
        self.transport.write(self.factory.getUser(user)+
b"
\r\n")
        self.transport.loseConnection()

class FingerFactory(protocol.ServerFactory):
    protocol = FingerProtocol

def getUser(self, user):
        return b"No such user"

fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
fingerEndpoint.listen(FingerFactory())
reactor.run()
'''

'''
# 4 factory
丰富一些了,有了一些方法和属性
# Read username, output from non-empty factory, drop connections

from twisted.internet import protocol, reactor, endpoints
from twisted.protocols import basic

class FingerProtocol(basic.LineReceiver):
    def lineReceived(self, user):
       
self.transport.write(self.factory.getUser(user) + b"
\r\n")
        self.transport.loseConnection()

class FingerFactory(protocol.ServerFactory):
    protocol = FingerProtocol

def __init__(self, users):
        self.users = users

def getUser(self, user):
        return self.users.get(user,
b"No such user")

fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
fingerEndpoint.listen(FingerFactory({ b'moshez' : b'Happy and well'}))
reactor.run()
'''

'''
# 5
加入了deferreds,并为它声明了callback和errback
# Read username, output from non-empty factory, drop connections
# Use deferreds, to minimize synchronicity assumptions

from twisted.internet import protocol, reactor, defer, endpoints
from twisted.protocols import basic

class FingerProtocol(basic.LineReceiver):
    def lineReceived(self, user):
        d = self.factory.getUser(user)

def onError(err):
            return 'Internal error in
server'
        d.addErrback(onError)

def writeResponse(message):
            self.transport.write(message
+ b'
\r\n')
           
self.transport.loseConnection()
        d.addCallback(writeResponse)

class FingerFactory(protocol.ServerFactory):
    protocol = FingerProtocol

def __init__(self, users):
        self.users = users

def getUser(self, user):
        return
defer.succeed(self.users.get(user, b"No such user"))

fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
fingerEndpoint.listen(FingerFactory({b'moshez': b'Happy and well'}))
reactor.run()
'''

'''
# 6 application
使用

from twisted.application import service, strports
from twisted.internet import protocol, reactor, defer
from twisted.protocols import basic

class FingerProtocol(basic.LineReceiver):
    def lineReceived(self, user):
        d = self.factory.getUser(user)

def onError(err):
            return 'Internal error in
server'
        d.addErrback(onError)

def writeResponse(message):
            self.transport.write(message
+ b'
\r\n')
           
self.transport.loseConnection()
        d.addCallback(writeResponse)

class FingerFactory(protocol.ServerFactory):
    protocol = FingerProtocol

def __init__(self, users):
        self.users = users

def getUser(self, user):
        return
defer.succeed(self.users.get(user, b"No such user"))

application = service.Application('finger', uid=1, gid=1)
factory = FingerFactory({b'moshez': b'Happy and well'})
strports.service("tcp:79", factory,
reactor=reactor).setServiceParent(
   
service.IServiceCollection(application))

'''

7.     
参考文档:

https://twistedmatrix.com/documents/current/core/howto/tutorial/intro.html

笔记-twisted的更多相关文章

  1. 笔记-twisted源码-import reactor解析

    笔记-twisted源码-import reactor解析 1.      twisted源码解析-1 twisted reactor实现原理: 第一步: from twisted.internet ...

  2. twisted学习笔记No.3 Web Clients

    原创博文,转载请注明出处. 这一章我们学习利用twisted建立web 客户端. twisted.web.client.getPage用来异步下载一个页面,并且返回一个deferred from tw ...

  3. twisted学习笔记 No.1

    原创博文,转载请注明出处 . 1.安装twisted ,然后安装PyOpenSSL(一个Python开源OpenSSL库),这个软件包用于给Twisted提供加密传输支持(SSL).最后,安装PyCr ...

  4. 笔记-scrapy与twisted

    笔记-scrapy与twisted Scrapy使用了Twisted作为框架,Twisted有些特殊的地方是它是事件驱动的,并且比较适合异步的代码. 在任何情况下,都不要写阻塞的代码.阻塞的代码包括: ...

  5. twisted 学习笔记二:创建一个简单TCP客户端

    #coding=utf-8 from twisted.internet import reactor,protocol class QuickClient(protocol.Protocol): de ...

  6. twisted学习笔记 No.2 WebServer

    原创博文,转载请注明出处. 当服务器接收到一个客户端请求后,会创建一个请求对象并传递到资源系统,资源系统会根据请求路径分发到相应的资源对象,资源被要求渲染自身并返回结果到客户端. 解析HTTP Req ...

  7. twisted学习笔记4 部署Twisted 应用程序

    原创博文,转载请注明出处. Twisted是一个可扩展,跨平台的网络服务器和客户端引擎. Twisted Application 框架有五个主要基础部分组成:服务,应用程序,TAC文件插件和twist ...

  8. twisted 学习笔记一:事件循环

    from twisted.internet import reactor import time def printTime(): print "Current time is", ...

  9. 游戏服务器学习笔记 5———— twisted Perspective Broker 透明代理

    实际上这章压根不需要我来说,twisted官网的Doc里面有专门介绍的章节.写的非常详细. http://twistedmatrix.com/documents/current/core/howto/ ...

随机推荐

  1. h5:WebSocket

    实时 Web 应用的窘境 Web 应用的信息交互过程通常是客户端通过浏览器发出一个请求,服务器端接收和审核完请求后进行处理并返回结果给客户端,然后客户端浏览器将信息呈现出来,这种机制对于信息变化不是特 ...

  2. CAD鼠标移动到对象时显示对象内容

    //定义事件         Editor ed = doc.Editor;         ed.PointMonitor += new PointMonitorEventHandler(ed_Po ...

  3. 菜鸟 学注册机编写之 Android app

    0x00前言 环境及工具: 手机    Nexus 4(己root) 系统版本    Android 5.01 工具    AndroidKiller_V1.2 关于Android平台app注册机的编 ...

  4. 2.eclipse安装

    1.进入官网https://www.eclipse.org/ 2.配置工作目录:存放 1.项目代码    2.IDE相关配置信息 3.没有配置tomcat,所以为空.

  5. 《转化:提升网站流量和转化率的技巧》:结合市场营销六阶段理论,以SEM为手段,提高网站转化率的技巧

    全书结合市场营销的六阶段理论,讲述各阶段的营销方面的要点和网站上吸引访客的技巧.举了一些例子,列举了一些工具.当然都是美国市场中的例子和网站优化的工具. 没有太多的新意.没看过相关图书的可以看看.

  6. 最长上升子序列&&最长不下降子序列

    百练2757: 题目描述: 对于给定的序列,求出最长上升子序列的长度. 题目链接:http://bailian.openjudge.cn/practice/2757 解题思路 一.动态规划 1. 找子 ...

  7. 2018.8.15 AOP面向切面编程简单理解

    在Filter过滤器中 拦截器 表面上看 -拦截器帮我们封装了很多功能 拦截器优秀的设计,可拔插设计 aop思想 在struts2中 归纳总结

  8. Spring boot 自动配置自定义配置文件

    示例如下: 1.   新建 Maven 项目 properties 2.   pom.xml <project xmlns="http://maven.apache.org/POM/4 ...

  9. mac jdk profile 永久的配置

    配置java_home 在MAC中设置JAVA_HOME环境变量 环境变量要再etc目录下的profile文件中配置,这样才是永久的配置. cd /etc vi profile 按 i 键进入写模式 ...

  10. 错误:javax.servlet.http.HttpServlet" was not found on the Java Build Path

    我们在用Eclipse进行Java web开发时,可能会出现这样的错误: The superclass javax.servlet.http.HttpServlet was not found on ...