当前位置: 首页 > 编程日记 > 正文

Twisted入门教程(3)

第三部分:开始认识Twisted

可以从这里从头开始阅读这个系列。


twisted的方式实现前面的内容

最终我们将使用twisted的方式来重新实现我们前面的异步模式客户端。不过,首先我们先稍微写点简单的twisted程序来认识一下twisted

最最简单的twisted程序就是下面的代码,其在twisted-intro目录中的basic-twisted/simple.py中。

from twisted.internet import reactor

reactor.run()

可以用下面的命令来运行它:

python basic-twisted/simple.py

正如在第二部分所说的那样,twisted是实现了Reactor模式的,因此它必然会有一个对象来代表这个reactor或者说是事件循环,而这正是twisted的核心。上面代码的第一行引入了reactor,第二行开始启动事件循环。

这个程序什么事情也不做。除非你通过ctrl+c来终止它,否则它会一直运行下去。正常情况下,我们需要给出事件循环或者文件描述符来监视I/O(连接到某个服务器上,比如说我们那个诗歌服务器)。后面我们会来介绍这部分内容,现在这里的reactor被卡住了。值得注意的是,这里并不是一个在不停运行的简单循环。如果你在桌面上有个CPU性能查看器,可以发现这个循环体不会带来任何性能损失。实际上,这个reactor被卡住在第二部分图5的最顶端,等待永远不会到来的事件发生(更具体点说是一个调用select函数,却没有监视任何文件描述符)

下面我们会让这个程序丰富起来,不过事先要说几个结论:

1.Twistedreactor只有通过调用reactor.run()来启动。

2.reactor循环是在其开始的进程中运行,也就是运行在主进程中。

3.一旦启动,就会一直运行下去。reactor就会在程序的控制下(或者具体在一个启动它的线程的控制下)。

4.reactor循环并不会消耗任何CPU的资源。

5.并不需要显式的创建reactor,只需要引入就OK了。

最后一条需要解释清楚。在Twisted中,reactorSingleton(也是一种模式),即在一个程序中只能有一个reactor,并且只要你引入它就相应地创建一个。上面引入的方式这是twisted默认使用的方法,当然了,twisted还有其它可以引入reactor的方法。例如,可以使用twisted.internet.pollreactor中的系统调用来poll来代替select方法

若使用其它的reactor,需要在引入twisted.internet.reactor前安装它。下面是安装pollreactor的方法

from twisted.internet import pollreactor

pollreactor.install()

如果你没有安装其它特殊的reactor而引入了twisted.internet.reactor,那么Twisted会为你安装selectreactor。正因为如此,习惯性做法不要在最顶层的模块内引入reactor以避免安装默认reactor,而是在你要使用reactor的区域内安装。

下面是使用 pollreactor重写上上面的程序,可以在basic-twisted/simple-poll.py文件中找到中找到:

from twited.internet import pollreactor

pollreactor.install()

from twisted.internet import reactor

reactor.run()

上面这段代码同样没有做任何事情。

后面我们都会只使用默认的reactor,就单纯为了学习来说 ,所有的不同的reactor做的事情都一样。


你好,Twisted

我们得用Twisted来做什么吧。下面这段代码在reactor循环开始后向终端打印一条消息:

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.

仍然需要你手动来关掉程序,因为它在打印完毕后就又卡住了。

值得注意的是,hello函数是在reactor启动后被调用的。这意味是reactor调用的它,也就是说Twisted在调用我们的函数。我们通过调用reactorcallWhenRunning函数,并传给它一个我们想调用函数的引用来实现hello函数的调用。当然,我们必须在启动reactor之前完成这些工作。

我们使用回调来描述hello函数的引用。回调实际上就是交给Twisted(或者其它框架)的一个函数引用,这样Twisted会在合适的时间调用这个函数引用指向的函数,具体到这个程序中,是在reactor启动的时候调用。由于Twisted循环是独立于我们的代码,我们的业务代码与reactor核心代码的绝大多数交互都是通过使用TwistedAPIs回调我们的业务函数来实现的。

我们可以通过下面这段代码来观察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()与我们自己的函数调用之间的关系即可。


有关回调的一些其它说明:

Twisted并不是唯一使用回调的框架。许多历史悠久的框架都已在使用它。诸多GUI的框架也是基于回调来实现的,如GTKQT

交互式程序的编程人员特别喜欢回调。也许喜欢到想嫁给它。也许已经这样做了。但下面这几点值得我们仔细考虑下:

1.reactor模式是单线程的。

2.Twisted这种交互式模型已经实现了reactor循环,意味无需我们亲自去实现它。

3.我们仍然需要框架来调用我们自己的代码来完成业务逻辑。

4.因为在单线程中运行,要想跑我们自己的代码,必须在reactor循环中调用它们。

5.reactor事先并不知道调用我们代码的哪个函数

这样的话,回调并不仅仅是一个可选项,而是游戏规则的一部分。

6说明了回调过程中发生的一切:

第三部分:初步认识Twisted

6 reactor启用回调

6揭示了回调中的几个重要特性:

1.我们的代码与Twisted代码运行在同一个进程中。

2.当我们的代码运行时,Twisted代码是处于暂停状态的。

3.同样,当Twisted代码处于运行状态时,我们的代码处于暂停状态。

4.reactor事件循环会在我们的回调函数返回后恢复运行。


在一个回调函数执行过程中,实际上Twisted的循环被有效地阻塞在我们的代码上。因此,因此我们应该确保回调函数不要浪费时间(尽快返回)。特别需要强调的是,我们应该尽量避免在回调函数中使用会阻塞I/O的函数。否则,我们将失去所有使用reactor所带来的优势。Twisted是不会采取特殊的预防措施来防止我们使用可阻塞的代码的,这需要我们自己来确保上面的情况不会发生。正如我们实际所看到的一样,对于普通网络I/O的例子,由于我们让Twisted替我们完成了异步通信,因此我们无需担心上面的事情发生。

其它也可能会产生阻塞的操作是读或写一个非socket文件描述符(如管道)或者是等待一个子进程完成。

如何从阻塞转换到非阻塞操作取决你具体的操作是什么,但是也有一些Twisted APIs会帮助你实现转换。值得注意的是,很多标准的Python方法没有办法转换为非阻塞方式。例如,os.system中的很多方法会在子进程完成前一直处于阻塞状态。这也就是它工作的方式。所以当你使用Twisted时,避使用os.system


退出Twisted

原来我们可以使用reactorstop方法来停止Twistedreactor。但是一旦reactor停止就无法再启动了。(Dave的意思是,停止就退出程序了),因此只有在你想退出程序时才执行这个操作。

下面是退出代码,代码文件是basic-twisted/countdown.py

class Countdown(object):

counter = 5

def count(self):

from twisted.internet import reactor

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函数为Twisted注册了一个回调函数。callLater中的第二个参数是回调函数,第一个则是说明你希望在将来几秒钟时执行你的回调函数。那Twisted如何来在指定的时间执行我们安排好的的回调函数。由于程序并没有监听任何文件描述符,为什么它没有像前那些程序那样卡在select循环上?select函数,或者其它类似的函数,同样会接纳一个超时参数。如果在只提供一个超时参数值并且没有可供I/O操作的文件描述符而超时时间到时,select函数同样会返回。因此,如果设置一个0的超时参数,那么会无任何阻塞地立即检查所有的文件描述符集。

你可以将超时作为图5中循环等待中的一种事件来看待。并且Twisted使用超时事件来确保那些通过callLater函数注册的延时回调在指定的时间执行。或者更确切的说,在指定时间的前后会执行。如果一个回调函数执行时间过长,那么下面的延时回调函数可能会被相应的后延执行。TwistedcallLater机制并不为硬实时系统提供任何时间上的保证。

下面是上面程序的输出:

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


捕获它,Twisted

由于Twisted经常会在回调中结束调用我们的代码,因此你可能会想,如果我们的回调函数中出现异常会发生什么状况。(Dave的意思是说,在结束我们的回调函数后会再次回到Twisted代码中,若在我们的回调中发生异常,那是不是异常会跑到Twisted代码中,而造成不可想象的后果 )让我们来试试,在basic-twisted/exception.py中的程序会在一个回调函数中引发一个异常,但是这不会影响下一个回调:

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.

注意,尽管我们看到了因第一个回调函数引发异常而出现的跟踪栈,第二个回调函数依然能够执行。如果你将reactor.stop()注释掉的话,程序会继续运行下去。所以说,reactor并不会因为回调函数中出现失败(虽然它会报告异常)而停止运行。

网络服务器通常需要这种健壮的软件。它们通常不希望由于一个随机的Bug导致崩溃。也并不是说当我们发现自己的程序内部有问题时,就垂头丧气。只是想说Twisted能够很好的从失败的回调中返回并继续执行。


请继续讲解诗歌服务器

现在,我们已经准备好利用Twisted来搭建我们的诗歌服务器。在第4部分,我们会实现我们的异步模式的诗歌服务器的Twisted版。


相关文章:

openstack高可用方案

openstack高可用方案 HA 将服务分为两类&#xff1a; • 有状态服务&#xff1a;后续对服务的请求依赖于之前对服务的请求。OpenStack中有状态的服务包括MySQL数据库和AMQP消息队列。对于有状态类服务的HA&#xff0c;如neutron-l3-agent、neutron-metadata-agent、nova-comput…

3D游戏设计和创作工具学习教程 3D Game Design Creation Tools

语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; 大小解压后&#xff1a;1.94G 1280X720 mp4 三维游戏设计和创作工具 用扎实的工作流程开始开发游戏 课程获取&#xff1a;3D游戏设计和创作工具学习教程 3D Game Design & Creation Too…

Java学习总结:53(单对象保存父接口:Collection)

单对象保存父接口&#xff1a;Collection java.util.Collection是进行单对象保存的最大父接口&#xff0c;即每次利用Collection接口都只能保存一个对象信息。单对象保存父接口定义如下&#xff1a; public interface Collection<E> extends Iterable<E>由该定义…

ORA-00942:表或视图不存在(低级错误)

在好多时候。调试PL/SQL对象时会报。ORA-00942 看看错误原因吧&#xff1a; 报错原因&#xff1a;1.该schema没有对表或者视图没有select权限 2.就是该对象不存在 解决的方法&#xff1a; 1.授权给对应对象 2.create table or view 转载于:https://www.cnblogs.com/blfshiye/p/…

2022-2028年中国蛋白石行业发展现状分析及投资前景趋势报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国蛋白石行业市场行业相关概述、中国蛋白石行业市场行业运行环境、分析了中国蛋白石行业市场…

实验: VMware使用快照间接备份原始VMDK文件

资料上看的使用快照备份运行着的虚拟机 当虚拟机开着时&#xff0c;快照提供了一个备份原始 VMDK 文件的好办法。所有的写入操作在原始文件上暂停了&#xff0c;因此&#xff0c;复制它在另一个存储卷很安全。这就是像 VMware Consolidated Backup 和 Vizioncore 的 vRanger…

tomcat生成catalina.out文件

生成catalina.out方法 导语&#xff1a;本文为Windows下生tomcat将控制台信息输出到catalina.out文件 且 保证能实时查看日志文件的方法。 一、创建catalina.out 1、修改tomcat bin目录下的startup.bat文件 修改位置&#xff1a;在startup.bat文件倒数第二行 修改call "%…

Unity优化手机游戏学习教程

流派:电子学习| MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;48.0 KHz 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09;|大小解压后:3.69 GB |时长:6h 44m 创建移动游戏的优化技巧和技术 你会学到什么 如何优化手机游戏的图形和…

Java学习总结:54(集合输出)

集合输出 在Java中&#xff0c;集合的输出操作有四种形式&#xff1a;Iterator输出、ListIterator输出、foreach(加强型for循环)输出、Enumeration输出。 迭代输出&#xff1a;Iterator Iterator(迭代器)是集合输出操作中最常用的接口&#xff0c;而在Collection接口中也提供…

12.27评论5位同学试验三

23号李名贵&#xff0c;http://www.cnblogs.com/xieqiuyou/p/5017244.html#3323660 写的不错&#xff0c;每行语句都有注释&#xff0c;但截图不完整 24号施振成&#xff0c;http://www.cnblogs.com/nonecanstop/p/5079334.html 写的较完整&#xff0c;轮转法和优先算法都有用到…

2022-2028年中国袋式除尘用滤料行业市场全景评估及发展策略分析报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国袋式除尘用滤料行业市场行业相关概述、中国袋式除尘用滤料行业市场行业运行环境、分析了中…

TL-WDN3321 Ubuntu 下安装

为什么80%的码农都做不了架构师&#xff1f;>>> The WiFi USB dongles based on the newest RT5572 chip set do not work out of the box on Ubuntu. Unex DNUR-V72, D-Link DWA-160 Rev B and TP-Link TL-WDN3200 dongles are based on this chipset. You will …

解决真机编译出现System.DllNotFoundException: 'libmono-native.so'错误都方法

1、去掉勾选&#xff1a;使用共享运行时 2 检查android SDK是否安装了NDK 3、使用真机运行编译APK 转载于:https://www.cnblogs.com/CelonY/p/11355417.html

Revit: Twinmotion工作流程学习

Revit: Twinmotion Workflow MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;44.1 KHz&#xff0c;2 Ch 技能等级:中级|语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; |时长:1h 22m |大小解压后:2.93 GB 含课程文件 Twinmotion是…

Java学习总结:55(偶对象保存:Map接口)

偶对象保存&#xff1a;Map接口 我们前面讲到的Collection属于单值保存父接口&#xff0c;每次只能保存一个对象&#xff1b;而我们这节讲的Map属于偶对象保存接口&#xff0c;利用Map可以保存一对关联数据(按照"key value"的形式)。 Map接口的常用方法 No方法名…

WPF的图片操作效果(一):RenderTransform

一.RenderTransform类的成员&#xff1a; 1.TranslateTransform 平移效果 2.RotateTransform 旋转效果 3.ScaleTransform 缩放效果 4.SkewTransform 扭转效果 5.TransformGroup 组合效果 6.MatrixTransform 是其他几个变形类的基类…

2022-2028年中国大气污染防治产业投资分析及前景预测报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国大气污染防治行业市场行业相关概述、中国大气污染防治行业市场行业运行环境、分析了中国大…

最近做手机端,GPS,微信QQ分享总结的问题

Android端 百度地图&#xff1a; 1.libs包中armeabi下liblocSDK4d.so文件丢失&#xff0c;导致百度定位失效。 微信分享&#xff1a; 1.分享App,app的内容&#xff08;图片加描述&#xff09;不能超过32kb &#xff0c;不然无法分享。&#xff08;直接跳至Oncancel事件中&#…

cap理论与分布式事务的解决方案

现在很火的微服务架构所设计的系统是分布式系统。分布式系统有一个著名的CAP理论&#xff0c;即一个分布式系统要同时满足一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availablility&#xff09;和分区容错&#xff08;Partition Tolerance&#xff09;三个…

Blender中的多平面动画学习教程

技能分享–Blender中的多平面动画 Skillshare – Multiplane Animation in Blender 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; 大小解压后&#xff1a;1.34G 含课程素材 信息: 我们将在这堂课中致力于创建一个2D多平面相机效果&#xf…

BestCoder Round #68 (div.2) 1002 tree

题意&#xff1a;给你一个图&#xff0c;每条边权值0或1&#xff0c;问每个点周围最近的点有多少个&#xff1f; 思路&#xff1a;并查集找权值为0的点构成的连通块。 1 #include<stdio.h>2 #include<string.h>3 #include<stdlib.h>4 #include<math.h>…

Java学习总结:56(Stack子类)

Stack子类 Stack表示栈操作&#xff0c;栈也是一种动态对象数组&#xff0c;采用的是一种先进后出的数据结构形式&#xff0c;即在栈中最早保存的数据最后才会取出&#xff0c;而最后保存的数据可以最先取出。Stack类的定义如下&#xff1a; public class Stack<E>exte…

2022-2028年中国大理石料行业市场研究及前瞻分析报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国大理石料行业市场行业相关概述、中国大理石料行业市场行业运行环境、分析了中国大理石料行…

ActionScript 3操作XML 详解

AS3引入了E4X &#xff0c;它是根据ECMAScript标准处理XML 数据的全新机制。这使得程序员在程序中无缝地操作XML。在AS3中可以使用XML字面值将XML数据直接写入代码&#xff0c;该字面值将被自动解析。 一、AS3中的XML入门 1.可以将XML直接写入代码 public var employeelist:XML…

kubernetes关键特性和概述

kubernetes关键特性和概述 https://blog.csdn.net/u014042372/article/details/80573213 posted on 2019-08-16 11:23 竹径风声 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/girl1314/p/11362768.html

Blender创作你自己的动画短片学习教程

Filmmaking with Blender – Create your own animated Short Film 时长:1h 20m |视频:. MP4 1280720&#xff0c;30 fps(r) |音频:AAC&#xff0c;44100 Hz&#xff0c;2ch |大小:1G 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; 在本课…

Java学习总结:57(Properties子类)

Properties子类 Properties类本身是Hashtable的子类&#xff0c;但是由于Properties类都使用String数据类型进行操作&#xff0c;所以在使用Properties类时主要使用本类所定义的方法。Properties类常用方法如下&#xff1a; No.方法类型描述1public Object setProperty(Strin…

openwrt入门

一、安装Ubuntu(在vware安装) 注意使用图形系统 二、安装openwrt开发工具 1.打开命令窗CtrlAltT&#xff0c;切换到root用户&#xff1a;sudo -sH或sudo su&#xff0c;退出root用户&#xff1a;CtrlD或exit 2.切换到root&#xff0c;下载安装组件&#xff08;apt-get install …

2022-2028年中国大飞机项目产业链分析及投资咨询报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国大飞机项目行业市场行业相关概述、中国大飞机项目行业市场行业运行环境、分析了中国大飞机…

一种可以避免数据迁移的分库分表scale-out扩容方式

原文地址&#xff1a;http://jm-blog.aliapp.com/?p590目前绝大多数应用采取的两种分库分表规则mod方式dayofweek系列日期方式&#xff08;所有星期1的数据在一个库/表,或所有?月份的数据在一个库表&#xff09;这两种方式有个本质的特点&#xff0c;就是离散性加周期性。例如…