什么也不做,the twisted way
最后我们决定重新用twisted来实现我们异步的读诗的客户端.但首先让我们写一些twisted代码找找twisted 的感觉.

下面是一个简单到屁的twisted程序,源码在basic-twisted/simple.py

from twisted.internet import reactor
reactor.run()

你可以像这样运行它:

python basic-twisted/simple.py

就像我们在第二部分所说的,twisted 是一个反应器模式的实现,包含一个反应器或者被叫做事件循环的对象,这个对象是twisted 程序的核心.在上面的程序中的第一行我们导入reactor,第二行告诉reactor去执行一个事件循环.
这个程序事实上什么也没做,你可以用Control-C停止他,否则的话他会永远执行下去.一般来说我们应该给事件循环一个或者多个文件描述符让事件循环来监测I/O,我们后面会讲到该怎么做,但现在反应器的事件循环是卡住的,记住反应器的事件循环不是一个不停循环的繁忙的循环,如果你可以监测cpu的使用情况,你可以发现这个reactor 是不耗费cpu资源的,这个反应器的事件循环会在图片五的顶部卡住,等待将要来的事件.

这个程序仍然是一个相当简单的程序,完全没有吸引力是吧? 我们接下来会做点有趣的事,不过我们已经可以得出下面的结论:

twsited 的reactor 不会自动开始运行,你可以让它运行起来通过reactor.run()
    反应器的循环(reactor loop)和它开始运行的地方运行在同一线程内,在这种情况下,他运行在主线程内
    一但事件循环运行起来,就会永远运行下去.这时reactor受程序控制
    如果没有什么事情可做,反应器的循环不耗费CPU资源
    reactor 不用创建,直接import进来就可以用

最后一点需要解释一下,在twisted中, reactor 是单例模式的.在一个twisted程序中只有一个reactor object,在你用import导入的时候就被创建了.如果你打开reactor 的源码,你会发现只有很少的代码,reactor 的真正实现在twisted.internet.selectreactor.

twisted 中有多种reactor 的实现.在第二部分已经提到,select 仅仅是其中的一中实现方法,也是twisted默认使用的方法.twisted中也包含其他的reactor 的实现方式,比如twisted.internet.pollreactor使用poll 的方式来实现.

如果要使用其他的reactor,你必须要在导入twisted.internet.reactor前先安装一下,你可以这样来安装pollreactor:

from twisted.internet import pollreactor
pollreactor.install()

如果你在导入twisted.internet.reactor之前没有安装其他的reactor 实现,twisted默认选择selectreactor.所以一般的不要在一个模块的上层导入reactor用来避免不经意的安装了默认的reactor,相反的,要在你要引用reactor 的时候再去导入它.
Note:自从写这些文章开始,twisted正在慢慢的转向允许多种reactor 同时存在的结构(应该是这样翻译),在计划中,一个reactor对象被传递的时候只作为一个引用而不是从一个模块中导入.
Note:不是所有的操作系统都支持poll,如果你的系统不支持,上面的例子在你的系统跑不起来
现在我们可以用pollreactor重新实现我们的第一个 twisted 程序,你可以在basic-twisted/simple-poll.py看到源码:

from twisted.internet import pollreactor
pollreactor.install()
from twisted.internet import reactor
reactor.run()

好吧,我们又非常成功的实现了一个什么也不做的poll 循环.
我们在以后的教程中都会使用使用twisted 的默认的reactor,为了学习twisted的话,所有的reactor都执行相同的功能.

Hello Twisted
下面让我们实现一个做点东西的twisted程序,下面的程序会打印两行消息:

def hello():
    print 'Hello from the reactor loop!'
    print 'Lately I feel like I\'m stuck in a rut.'

from twisted.internet import reactor

reactor.callWhenRunning(hello)

print 'Starting the reactor.'
reactor.run()

程序代码在 basic-twisted/hello.py,如果你运行的话,会看到以下的输出:

Starting the reactor.
Hello from the reactor loop!
Lately I feel like I'm stuck in a rut.

需要你手动杀死这个程序,因为当执行完print 之后程序会卡住.

hello 函数是在reactor 运行之后被调用的,这就意味这hello函数是被reactor调用的,所以twisted的代码必须可以调用我们的定义的函数,我们让callwhenrunning 传递一个hello函数的引用到twisted code,并触发callwhenrunning.但让必须在ractor运行之后才可以.
我们用术语callback来描述这种引用, 一个callback 是我们给twisted的一个函数的引用,twisted 会call back 在正确的时候.既然twisted 和我们的业务逻辑是分开的,reactor 和我们的业务逻辑通过callback一个函数来进行交互.
我们可以看到下面的程序看到twisted怎样和我们的程序交互的:

import traceback

def stack():
    print 'The python stack:'
    traceback.print_stack()

from twisted.internet import reactor
reactor.callWhenRunning(stack)
reactor.run()

你可以在basic-twisted/stack.py看到源代码,会输出一些像下面的东西:

The python stack:
...
reactor.run() <-- This is where we called the reactor
...
... <-- A bunch of Twisted function calls
...
traceback.print_stack() <-- The second line in the stack function

不要在意中间的一些twisted之间的调用,注意reactor.run() 和我们的callback之间的关系

callback 是做什么的
twisted 不是唯一一个用callback 的reactor 框架, 其他的异步框架Medusa和asyncore也在用,还有一个GUI 比如GTK和QT,也是基于reactor循环的.
"反应器"系统的开发者们非常爱callback,但是要考虑到下面几点:

反应堆模式是单线程的

一个reactor的框架比如twisted实现了reactor循环所以我们的代码不要再去实现了
    我们的代码仍旧需要被调用来实现我们的业务逻辑
    既然整个程序在单线程内,reactor循环仍需要调用我们的代码
    reactor不能事先知道我们哪部分代码需要被调用

考虑到上面几点,callback就是必须的了

图片六描述了callback 的时候发生了什么

图片六

图片六说明一些callback 的重要属性:

我们的callback 代码和twisted 循环运行在同一个线程中

当我们的callback在运行的时候,twisted 循环不运行
    同上,当twisted 循环运行时,callback是不运行的
    reactor循环恢复,当我们的callback返回时

在一个callback中,twisted 循环可以看作是被阻塞住了.所以我们应该确保我们的callback代码不要花费很多时间.通常的,我们应该在我们的callback中避免阻塞的I/O操作.否则我们使用反应器模式的好处就不存在了.twisted 不会提供任何防范方法去阻止你的阻塞程序,我们必须确保在callback中不要做阻塞操作.不过最后你会发现,我们不用担心基本的网络I/O操作,因为我们可以让twisted去为我们实现异步通信.

其他的可能出现阻塞的操作包括从不是socket 文件描述符(比如pipe)中读写,或者等待一个子进程结束.怎样把阻塞的操作编程的非阻塞的操作跟你要完成什么有很大的关系,但是总会有twisted api 可以帮助实现它.记住,一些标准的python 函数本身就是阻塞模式的,没有方法转为非阻塞模式,比如,os.system 函数会阻塞直到子进程运行完成,他们就是那样工作的,所以在你用twisted的时候,你应该避免在你的代码中使用这些阻塞函数. Goodbye Twisted

你可以让twisted 的reactor 停止运行通过 reactor 的stop方法.但是一但reactor 被停止它不能被重启,所以在你的程序不得不停止的时候再去调用reactor 的stop方法. 曾经在邮件列表中讨论过让reactor变为可重启动的,你可以控制reactor 什么时候开始,什么时候停止.在twisted 8.2.0中,你仅仅可以启动reactor一次

下面有一个程序,basic-twisted/countdown.py,在5秒后停止reactor:

class Countdown(object):

counter = 5

def count(self):
        if self.counter == 0:
            reactor.stop()
        else:
            print self.counter, '...'
            self.counter -= 1
            reactor.callLater(1, self.count)

from twisted.internet import reactor

reactor.callWhenRunning(Countdown().count)

print 'Start!'
reactor.run()
print 'Stop!'

这个程序用callLater API 注册了一个callback,这个callback作为callLater 的第二参数,第一个参数是等待多少秒然后你的callback才被执行.

twisted 是怎样在正确的实行去执行callback 的?既然这个程序没有监听任何的文件描述符,为什么也会在select循环中被卡住呢? 事实是,select 还有其他的类似的poll 也接收一个可选的timeout值,如果在一个timeout 的时间周期内没有任何一个文件描述符可以读写,select 也会返回.如果你传递给timeout 一个0值,你可以没有阻塞的监听文件描述符.
你可以把timeout 想象成一个事件循环正在等的事件(参照图片五),twisted 用timeout 来确保任何一个被定时了的callback可以在正确的时间运行.假如一个callback需要花费很长的时间,一个定时的callback会被顺延,所以twisted 的callLater 机制不能提供非常准确的时间保证.
下面是这个程序的输出

Start!
5 ...
4 ...
3 ...
2 ...
1 ...
Stop!

最后会输出一个stop表示reactor 已经退出了,现在有了一个可以自己的停止的程序了.
接招吧 (让我想起了take that 乐队)twisted
既然twisted 以callback的方法来执行我们的方法,你会想如果一个callback抛出了异常怎么办.让我们试试吧,basic-twisted/exception.py会在一个callback中抛出一个异常:

def falldown():
    raise Exception('I fall down.')

def upagain():
    print 'But I get up again.'
    reactor.stop()

from twisted.internet import reactor

reactor.callWhenRunning(falldown)
reactor.callWhenRunning(upagain)

print 'Starting the reactor.'
reactor.run()

你会看到以下输出:

Starting the reactor.
Traceback (most recent call last):
  ... # I removed most of the traceback
exceptions.Exception: I fall down.
But I get up again.

注意第二个callback仍会在第一个callback之后运行,即使我们看到了很多的异常的追踪信息.如果你把reactor.stop()注释掉的话,这个程序会仍会继续运行下去,所以reactor 会继续运行下去即使我们的一个callback抛出了异常,
网络服务器对鲁棒性要求比较高,即使在运行过程中出现了一些bug也不能让服务器down掉,不是在说我们不用去处理我们的错误,如果你感觉后面还有人支持着你,你会感觉很棒.
Poetry,please
下面我们要twisted去获取点小诗啦,在第四部分,我们会实现一个twised 的异步的客户端

python twisted教程 三–开始twisted相关推荐

  1. python twisted教程_Python使用Twisted总结

    最近一直想把Python的Twisted框架好好学习学习,但苦于在生产环境中没有实际的应用,参考网上关于Twisted系列教程,决定深入学习下.Twisted起源于一款游戏,并在游戏中用于商业活动中, ...

  2. python twisted教程_python中twisted实例用法

    python 编程之twisted详解及简单实例 python 编程之twisted详解 前言: 我不擅长写socket代码.一是用c写起来比较麻烦,二是自己平时也没有这方面的需求.等到自己真正想了解 ...

  3. python twisted教程_twisted基础教程.pdf

    twisted基础教程 Twisted 网络编程必备(一) 0.1 为什么使用Twisted? 如果你并不准备使用Twisted,你可能有很多异议.为什么使用Twisted 而不是其他网络函数 库或框 ...

  4. twisted系列教程五–改进twisted poetry client

    在第四部分我们写了我们的第一个twisted client.它工作的非常好,但仍旧有提升的空间 首先,这个twisted client 包含了一些比如创建sockets 和从这些sockets 中接收 ...

  5. python基础教程免费下载-Python基础教程第三版PDF电子书免费下载

    <Python基础教程(第3版)>是2018年人民邮电出版社出版的图书,作者是[挪]Magnus Lie Hetland.该书全面介绍了Python的基础知识和基本概念,包括列表.元组.字 ...

  6. twisted系列教程十六–twisted守护进程

    Introduction 到目前为止我们写的server 还运行在一个终端里面,通过print 语句向外输出内容.开发的时候这样做是很有好处的,但是当你部署一个产品的时候这样就不好了.一个生产环境中的 ...

  7. python实现网络编程 之Twisted框架

    原文链接:http://www.aosabook.org/en/twisted.html 作者:Jessica McKellar Twisted是用Python实现的基于事件驱动的网络引擎框架.Twi ...

  8. python基础教程第二版和第三版哪个好-python基础教程 2版和3版哪个适合新手?!...

    python基础教程 2版和3版哪个适合新手? 现在学是学python3. 两者的差异发者本身影响并不大,个别语法细微的差比如python3的print数方式使用,一些常用模块的名称差异,一些机制的差 ...

  9. python基础教程第三版电子版百度云-《python基础教程第三版》高清版PDF免费下载...

    下载地址1:http://t.cn/EGxO1sW Python基础教程 第3版Python简明教程书籍 Python编程从入门到实践 灵程序设计丛书 <python基础教程第三版>高清版 ...

最新文章

  1. 使用opencv自带的融合函数
  2. About the windchill Command -
  3. matlab优化算法案例分析与应用_最优化计算与matlab实现(18)——粒子群优化算法——权重改进的粒子群算法...
  4. python清空文件夹
  5. 我整理了10张超酷炫的可视化大屏,新手也能做,秀到没朋友
  6. select样式调整
  7. 配置 .vimrc 解决 Vim / gVim 在中文 Windows 下的字符编码问题
  8. 贝尔英才学院计算机,特稿 | 从高三的二模倒数第一到考取南京邮电大学贝尔英才学院,他仅用了半年!...
  9. php连接mysql实例留言板_一个php留言板实例详解(附源码下载)
  10. HBase预分区设计
  11. 如何设计可靠的灰度方案
  12. 挑战性价比,刷新你对千元级投影仪的认知,这份详细评测送给你
  13. vue 关于图片和文字的绝对定位 js 动态设置定位
  14. 2021杭电多校第3场_HDU6975_Forgiving Matching
  15. RFSoC应用笔记 - RF数据转换器 -04- RFSoC关键配置之RF-ADC内部解析(二)
  16. wp7编程环境配置(包含xp下安装)
  17. 用ps魔棒工具选区域和改变区域颜色
  18. [Android][sensor]物理sensor bring up流程
  19. 2019年马上结束了,当初立的flag如何了?
  20. windows平台编译ffmpeg

热门文章

  1. 易生信极高性价比暑期黑马集训 -- 低至2500每人
  2. visual studio code怎么改成中文?Visual Studio Code Insiders for Mac中文修复版
  3. 第十一届蓝桥杯省赛 C++组试题 第2题 求完数
  4. Linux学习之C语言的进程与线程编程
  5. android 点击两次退出,Android实现点击两次返回键退出
  6. 【ES9(2018)】String 扩展 标签模板里字符串转义
  7. vue router 的两种路由模式hash与history的区别
  8. Python笔记-U2解锁手机九宫格
  9. HTTP之Cookie和Session(C++ Qt框架实现)
  10. C++ opengl GL_POLYGON的绘制