Twisted第三方文档:https://krondo.com/an-introduction-to-asynchronous-programming-and-twisted/
Twisted官方文档:https://twistedmatrix.com/trac/wiki/Documentation
1、Twisted框架介绍
- twisted是一个完整的事件驱动的网络框架,利用它既能使用也能开发完整的异步网络应用程序和协议。
- twisted提供了大量的支持来建立完整的系统,包括网络协议、线程、安全性和身份验证、聊天/IM、DBM及RDBMS数据库集成、Web/因特网、电子邮件、命令行参数、GUI集成工具包等。
- twisted不是Python标准库的一部分,所以必须单独下载并安装它。
2、Twisted的启动
1、Twisted的reactor对象
- Twisted是反应器模式的一个实现,因此包含一个代表反应器或事件循环的对象(即reactor对象),它是任何Twisted程序的核心。
- 在Twisted中,反应器基本上是一个Singleton。只有一个反应器对象,它是在导入时隐式创建的。如果你打开twisted.internet包中的reactor模块,你会发现只有很少的代码。实际的实现是在其他文件中(例如,参见twisted.internet.selectreactor)。
示例:最简单的Twisted程序
- 这个程序只是坐在那里什么都不做。你必须按Control-C来停止它,否则它会永远坐在那里。通常,我们会给循环一个或多个文件描述符,以便监控I/O。
- 请注意,这不是一个不断循环的繁忙循环。如果你的屏幕上恰好有一个CPU仪表,你不会看到这种技术上的无限循环引起的任何峰值。事实上,我们的程序根本没有使用任何CPU。相反,反应器停留在循环的顶部,等待一个永远不会出现的事件(具体来说,等待一个没有文件描述符的select调用)。
#程序路径D:\twisted-intro-master3\basic-twisted\simple.py
from twisted.internet import reactor #导入reactor对象
reactor.run() #reactor开始运行循环
#运行程序
PS C:\Users\root> python3 D:\twisted-intro-master3\basic-twisted\simple.py
2、reactor对象的总结
- Twisted的反应器循环只有接到指令才会启动。可以通过调用reactor.run()来启动它。
- 反应器循环在启动它的一个线程中运行。在本例中,它运行在主线程中(也是唯一的)。
- 一旦循环开始,它就会继续。反应器现在已经“控制”了程序(或者是启动它的特定线程)。
- 如果它没有任何事情要做,反应器循环不消耗CPU。
- 反应器不是显式创建的,只是导入。
3、其他reactor对象
- Twisted实际上包含多个反应器实现。select调用只是等待文件描述符的一种方法。Twisted包括几个使用不同方法的反应器实现。例如,twisted.internet.pollreactor使用poll系统调用而不是select。
- 要使用一个特定的反应器,你必须在导入twisted.internet.reactor之前安装它。下面是如何安装pollreactor:
from twisted.internet import pollreactor
pollreactor.install()
- 如果您在导入twisted.internet.reactor前没有先安装特定的reactor实现,那么Twisted将为您安装默认的reactor。默认的reactor取决于您所使用的操作系统和Twisted版本。出于这个原因,一般的做法是不要在模块的顶层导入反应堆,以避免意外安装默认反应堆
示例:使用pollreactor反应器重新实现第一个twisted程序
- 这是一个什么都不做的轮询循环,而不是一个什么都不做的选择循环。
#程序路径D:\twisted-intro-master3\basic-twisted\simple-poll.py
from twisted.internet import pollreactor
pollreactor.install()
from twisted.internet import reactor
reactor.run()
3、Twisted的回调
- Twisted不是唯一使用回调的反应器框架。较早的异步Python框架Medusa和asyncore也使用它们。GUI工具包GTK和QT也是如此,它们都像许多GUI框架一样,基于反应器循环。
示例:
- 这是在反应器循环启动后将消息打印到终端窗口的一个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()
<<<
Starting the reactor.
Hello from the reactor loop!
Lately I feel like I‘m stuck in a rut.
1、使用术语“回调”来描述对hello函数的引用
- 注意:hello函数在反应器开始运行后被调用。这意味着它由反应器本身调用,因此Twisted代码必须调用我们的代码。
- 通过reactor对象调用callWhenRunning方法(回调)来引用我们希望Twisted调用的函数。当然,必须在启动反应器之前这样做。
- 在反应器循环启动之后,Twisted将使用回调函数在适当的时间“回调我们的代码”
- 由于Twisted的循环与我们的代码是分开的,所以反应堆核心和我们的业务逻辑之间的大多数交互将从对我们使用各种API提供给Twisted的函数的回调开始。
2、反应器系统的开发者喜欢回调。但请思考:
- 反应器模式是单线程的。
- 像Twisted这样的反应式框架实现了reactor循环,因此我们的代码不必这样做。
- 我们的代码仍然需要被调用来实现我们的业务逻辑。
- 由于它在单线程中,因此反应器循环将不得不调用我们的代码。
- 反应器无法提前知道需要调用我们代码的哪一部分
3、回调期间发生的事情:

- 我们的回调代码与Twisted循环在同一线程中运行。
- 当我们的回调运行时,Twisted循环没有运行。
- 反之亦然。
- 当我们的回调返回时,反应器循环恢复。
- 在回调期间,Twisted循环被我们的代码有效地“阻塞”。
- 应该确保我们的回调代码不会浪费任何时间。
- 特别是,应该避免在回调中执行阻塞的I/O调用。否则,将失去使用反应器模式的全部意义。
- Twisted不会采取任何特别的预防措施来防止代码阻塞,我们只需要确保不这样做。
- 正如我们最终将看到的,对于网络I/O的常见情况,我们不需要担心它,因为我们让Twisted为我们做异步通信。
- 其他可能阻塞操作,包括从非套接字文件描述符(比如管道)读或写,或者等待子进程完成。从阻塞操作切换到非阻塞操作的方式具体取决于您正在做什么,但通常有一个Twisted API可以帮助您做到这一点。注意,许多标准Python函数无法切换到非阻塞模式。例如,该os.system函数将始终阻塞,直到子进程完成。因此,在使用Twisted时,你必须避免使用os.system支持Twisted API来启动子进程。
4、twisted的停止
- 可以使用反应器的stop方法告诉Twisted反应器停止运行。但是一旦停止反应器就无法重新启动,因此通常只有在程序需要退出时才执行此操作。
- 从Twisted8.2.0版本开始,只能启动(并因此停止)反应器一次。
示例:
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!‘)
<<<
Start!
5 ...
4 ...
3 ...
2 ...
1 ...
Stop!
python网络编程Twisted02 Twisted框架
原文:https://www.cnblogs.com/maiblogs/p/15098953.html