twisted 诗歌客户端代码分析:嵌套着的多层deferred。

Go defer 原理剖析篇 — 深度解密 defer 原理,究竟背着程序猿做了多少事情 文章目录编译器怎么编译 defer`struct _defer` 数据结构`struct _defer` 内存分配栈上分配 `deferprocStack`堆上分配 `deferproc`执行 defer 函数链( `deferreturn` )jmpdeferdefer 怎么传递参数?预计算参数defered 的参数准备一个函数多个 defer 语句的时候,会发生什么?defer 和 return 返回值运行顺序究竟是怎样的?函数的调用过程return 之后是先返回值还是先执行 defer 函数?总结 阅读详情

http://krondo.com/?p=2159

http://blog.sina.com.cn/s/blog_704b6af70100qay3.html

花了很长的时间才看懂了这段代码的运行过程。该代码是上面两个网页中的twisted 教程中的第13部分的内容,旨在使用嵌套式的deferred建立一个诗歌下载客户端。

这篇文章的主要难点在于对多层deferred的callback函数的调用顺序的理解。


1.服务器提供诗歌的下载和诗歌的转换,两个功能。

2.该客户端首先从服务器上面下载诗歌,之后再使用服务器,对诗歌进行转换。

3.建立两个protocol,两个Factory.

4.PoetryProtocol与PoetryClientFactory用于下载诗歌。

5.TransformClientProtocol与TransformClientFactory用于对诗歌进行转换。

6.在主函数main中进行了三次添加callback。分别为:

d.addCallback(try_to_cummingsify)

d.addCallbacks(got_poem,poem_failed)

d.addBoth(poem_done)

7.在get_poetry(host,port)中为外部的deferred生成处。该函数建立TCP链接,从服务器端下载诗歌。

如果下载成功则在poem_finished中调用callback。则try_to_cummingsify开始执行。

否则,在clientConnectionFailed中调用errback。则首先pass_through然后直接执行poem_failed,再执行peom_done结束。

8.在try_to_cummingsify中建立了一个内部deferred,并且建立TCP链接,传输当前poem到服务器,然后接受转换好了的poem。并且向内部的deferred添加了一个callback

d.addErrback(fail)

9.如果cummingsify成功,则调用handlePoem,在handlePoem调用callback。由于内部deferred中之添加了fail作为errback。因此这个callback是直接pass_through的。

10.如果cummingsify失败,则调用clientConnectionLost,在其中调用d.errback,此时实际上执行了fail函数。

11.这时候外层的try_to_cummingsify函数执行完毕。开始执行got_poem。如果cummingsify成功,这时的poem为cum后的poem。否则为原poem,因为fail函数返回原poem。

12.最后执行poem_done,结束。


源代码如下:

# This is the Twisted Get Poetry Now! client, version 6.0

import optparse, sys

from twisted.internet import defer
from twisted.internet.protocol import Protocol, ClientFactory
from twisted.protocols.basic import NetstringReceiver


def parse_args():
    usage = """usage: %prog [options] [hostname]:port ...

This is the Get Poetry Now! client, Twisted version 6.0
Run it like this:

python get-poetry.py xform-port port1 port2 ...

If you are in the base directory of the twisted-intro package,
you could run it like this:

python twisted-client-6/get-poetry.py 10001 10002 10003

to grab poetry from servers on ports 10002, and 10003 and transform
it using the server on port 10001.

Of course, there need to be appropriate servers listening on those
ports for that to work.
"""

    parser = optparse.OptionParser(usage)

    _, addresses = parser.parse_args()

    if len(addresses) < 2:
        print parser.format_help()
        parser.exit()

    def parse_address(addr):
        if ':' not in addr:
            host = '127.0.0.1'
            port = addr
        else:
            host, port = addr.split(':', 1)

        if not port.isdigit():
            parser.error('Ports must be integers.')

        return host, int(port)

    return map(parse_address, addresses)


class PoetryProtocol(Protocol):

    poem = ''

    def dataReceived(self, data):
        self.poem += data

    def connectionLost(self, reason):
        self.poemReceived(self.poem)

    def poemReceived(self, poem):
        self.factory.poem_finished(poem)


class PoetryClientFactory(ClientFactory):

    protocol = PoetryProtocol

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

    def poem_finished(self, poem):
        if self.deferred is not None:
            d, self.deferred = self.deferred, None
            d.callback(poem)

    def clientConnectionFailed(self, connector, reason):
        if self.deferred is not None:
            d, self.deferred = self.deferred, None
            d.errback(reason)


class TransformClientProtocol(NetstringReceiver):

    def connectionMade(self):
        self.sendRequest(self.factory.xform_name, self.factory.poem)

    def sendRequest(self, xform_name, poem):
        self.sendString(xform_name + '.' + poem)

    def stringReceived(self, s):
        self.transport.loseConnection()
        self.poemReceived(s)

    def poemReceived(self, poem):
        self.factory.handlePoem(poem)


class TransformClientFactory(ClientFactory):

    protocol = TransformClientProtocol

    def __init__(self, xform_name, poem):
        self.xform_name = xform_name
        self.poem = poem
        self.deferred = defer.Deferred()

    def handlePoem(self, poem):
        d, self.deferred = self.deferred, None
        d.callback(poem)

    def clientConnectionLost(self, _, reason):
        if self.deferred is not None:
            d, self.deferred = self.deferred, None
            d.errback(reason)

    clientConnectionFailed = clientConnectionLost


class TransformProxy(object):
    """
I proxy requests to a transformation service.
"""

    def __init__(self, host, port):
        self.host = host
        self.port = port

    def xform(self, xform_name, poem):
        factory = TransformClientFactory(xform_name, poem)
        from twisted.internet import reactor
        reactor.connectTCP(self.host, self.port, factory)
        return factory.deferred


def get_poetry(host, port):
    """
Download a poem from the given host and port. This function
returns a Deferred which will be fired with the complete text of
the poem or a Failure if the poem could not be downloaded.
"""
    d = defer.Deferred()
    from twisted.internet import reactor
    factory = PoetryClientFactory(d)
    reactor.connectTCP(host, port, factory)
    return d


def poetry_main():
    addresses = parse_args()

    xform_addr = addresses.pop(0)

    proxy = TransformProxy(*xform_addr)

    from twisted.internet import reactor

    poems = []
    errors = []

    def try_to_cummingsify(poem):
        d = proxy.xform('cummingsify', poem)

        def fail(err):
            print >>sys.stderr, 'Cummingsify failed!'
            return poem

        return d.addErrback(fail)

    def got_poem(poem):
        print poem
        poems.append(poem)

    def poem_failed(err):
        print >>sys.stderr, 'The poem download failed.'
        errors.append(err)

    def poem_done(_):
        if len(poems) + len(errors) == len(addresses):
            reactor.stop()

    for address in addresses:
        host, port = address
        d = get_poetry(host, port)
        d.addCallback(try_to_cummingsify)
        d.addCallbacks(got_poem, poem_failed)
        d.addBoth(poem_done)

    reactor.run()


if __name__ == '__main__':
    poetry_main()



爬虫日记(104):Twisted:客户端实现双向传送协议 前面实现了一个转换服务器的功能,它就是把客户端的发送过来的诗歌内容进行小写转换,然后再把转换之后的内容发送回去给客户端,这是一种RPC的调用过程。也是目前比较热门的微服务的变种。虽然这个例子比较简单,但是它实现了服务器的双向传送的功能,也演示了Twisted开发服务器的便捷性。有了服务器,那么我们就需要开发一个客户端才可以访问这个服务器了。在开发的过程中,我们面临着两个问题,第一个问题就是需要向多个服务器进行通讯,第二个问题是两个服务器之间进行的处理需要进行协调,比如下载诗歌服务器要先进行连接并进行下载,并 阅读详情

相关推荐

爬虫日记(100):Twisted:使用Deferred重构回调函数管理

前面的例子可以看到下载诗歌的例子里,使用回调函数来进行实现客户端的代码,这样需要传送两上回调函数进去,接着下来我们使用已经学习的Deferred类来管理回调函数,就不必要传送回调函数了,这样让代码更加简单,并且容易管理。 例子如下: # This is the Twisted Get Poetry Now! client, version 4.0 import optparse, sys from twisted.internet import defer from twisted.interne

大坡3D软件开发 451

大语言模型在学术写作中的应用与技术解析

大语言模型(LLM)作为自然语言处理的核心技术,通过深度学习实现文本生成与风格控制。其原理是基于海量语料训练,捕捉语言规律与上下文关联。在学术写作领域,LLM的价值体现在提升文献综述效率、优化实验方法描述及语言润色。典型应用场景包括自动生成结构化学术文本、调整学科特定写作风格等。技术实现上需针对学术语料进行特殊处理,如专业术语保留和引用格式标准化。当前主流工具如Scite.ai结合了可信度标注功能,而StyleTransfer等技术则实现期刊风格适配。合理使用这些工具时需注意学术伦理,人工校验仍是质量保障的

weixin_30414305的博客 521

【学习笔记】《基于φ-OTDR的分布式扰动传感系统定位算法研究-北交-通信与信息系统-吴》重点笔记

一、绪论 1.1 引言 光纤传感器的优点:跟电子传感器相比较,光纤传感器有诸多独特的优势:对电磁干扰免疫;具有很好的绝缘性和耐腐蚀性;灵敏度高,可测量微弱信息;可实现大范围监测和分布式传感,仅需一根传感光纤,更为经济便捷;传感光纤体积小、重量轻、可形变,适用于一些特殊应用场所;还有无需供电、耐高温、便于组网等等优点 光纤传感器的感知信号的方法:当探测光入射到光纤中时会发生散射并产生各种散射光...

qq_36045093的博客 2万+

GoLang之defer底层系列三(v 1.14)

GoLang之defer底层系列三(v 1.14)

weixin_52690231的博客 524

ROS2+MoveIt2+Gazebo仿真实战:从零搭建六轴机械臂控制闭环

本文详细介绍了如何从零搭建一个完整的ROS2+MoveIt2+Gazebo六轴机械臂仿真控制闭环。通过手写URDF模型、配置MoveIt2运动规划、集成Gazebo物理仿真与ROS2 Control控制器,最终实现RViz中规划轨迹、Gazebo中同步执行的完整数字孪生验证平台,为机器人算法开发和硬件验证提供低成本、高效的仿真解决方案。

weixin_29093017的博客 484

银河麒麟V11 + KVM/QEMU + GT 710 GPU直通 Win10 完整操作流程文档

宿主机:RTX 5080专门运行ollama大模型服务,通过SSH/VNC远程管理Win10虚拟机:GT 710直通,物理键盘专属,通过物理显示器处理视频应用硬件隔离:两个系统完全隔离,互不干扰,性能最大化两种不同的直通方式直通方式 配置方法 设备在宿主机的状态 典型应用场景PCIe设备直通 vfio-pci.ids=10de:128b,10de:0e0f 设备完全从宿主机消失,被vfio-pci驱动接管 GPU、网卡、NVMe硬盘。

weixin_45285654的博客 1151

GoLang之defer底层系列一(v 1.12)

GoLang之defer底层系列一(v 1.12)

weixin_52690231的博客 627

Docker部署 SRS rtmp/flv流媒体服务器

SRS(Simple Realtime Server)是一款开源的流媒体服务器,具有高性能、高可靠性、高灵活性的特点,能够支持直播、点播、转码等多种流媒体应用场景。SRS 不仅提供了流媒体服务器,还提供了适用于多种平台的客户端 SDK 和在线转码等辅助服务,是一款十分强大的流媒体解决方案。

m0_56659620的博客 4869

【go】defer底层原理

golang defer原理

weixin_40660221的博客 738

UE5实现建筑剖切效果

UE5实现建筑剖切效果

专注GIS开发 8462

单片机通过蜂鸣器播放任意音乐代码实现(2):音乐单片机代码自动生成

单片机通过蜂鸣器播放任意音乐代码实现(2):音乐单片机代码自动生成 上一节我们已经构建了基于51单片机的蜂鸣器音乐播放环境,接下来只需要手动或者自动添加音乐代码便能实现不同音乐的播放。当然,第二节将告诉你如何自动生成这些音乐代码。 所用软件 MuseScore 3;用于转换MID文件为musicxml文件 C/C++ IDE(本文为Visual Studio 2019) 1.生成音乐对应的MID文件 可以直接下载mid格式音乐文件,也可以将某段音乐转换为MID文件。最好是直接使用mid格式音乐文件,可

kevin1499的博客 2万+

jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)

Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html ******************构建Deferred对象时候的流程图************************** **********************源码解析********************** 因为cal...

baoaoba9317的博客 252

基于YOLOv8的植物生长阶段识别系统设计与实现

本文详细介绍了一个基于YOLOv8深度学习模型的植物生长阶段识别系统,包含完整的数据集构建、模型训练、评估以及基于PyQt5的用户界面开发过程。系统能够自动识别植物在不同生长阶段(如发芽期、生长期、开花期、结果期等)的形态特征,为精准农业和智能种植提供技术支持。文章提供了完整的代码实现,并讨论了模型优化策略和实际应用场景。关键词:植物生长阶段识别、YOLOv8、目标检测、PyQt5、深度学习。

YOLO 465

《网络安全自学教程》- Nmap使用及扫描原理分析

使用Nmap进行端口扫描、主机发现、服务识别、操作系统识别、指定脚本、结果导出文件,使用wireshark抓包分析扫描原理。

wangyuxiang946的博客 1万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

使用Deferred新功能实现新客户端

介绍 回忆下第10部分中的客户端5.1版。客户端使用一个Deferred来管理所有的回调链,其中包括一个格式转换引擎的调用。在那个版本中,这个引擎的实现是同步的。 现在我们想实现一个新的客户端,使用我们在第十二部分实现的服务器提供的格式转换服务。但这里有一个问题需要说清楚:由于格式转换服务是通过网络获取的,因此我们需要使用异步I/O。这也就意味着我们获取格式转换服务的API必须是异步实

小岁月太着急 368

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Twisted入门教程(13)

第十三部分 使用Deferred新功能实现新客户端你可以从这里从头阅读这个系列。介绍回忆下第10部分中的客户端5.1版。客户端使用一个Deferred来管理所有的回调链,其中包括一个格式转换引擎的调用。在那个版本中,这个引擎的实现是同步的。(即等待其执行再切到其它函数或任务中)现在我们想实现一个新的客户端,其使用我们在第十二部分实现的格式服务器提供的格式转换服务。但这里有一个问题需要说清楚:由于格...

weixin_34378969的博客 158

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

jquery deferred对象 then(),when()方法 ,解决回调函数嵌套

<script type="text/javascript"> $(document).ready(function() { var aa = $.Deferred(); var bb = $.Deferred(); var cc = $.Deferred(); /*先说一下then方法的使用*/ /

crystal0705的博客 2041

Scrapy Unhandled error in Deferred

Unhandled error in Deferred报错为 Exception ignored in: &lt; generator object iter_errback at 0x0000028B0762A620&gt; RuntimeError: generator ignored GeneratorExit Unhandled error in Deferred2017-08-23 22:22:

lei396601057的博客 1万+

Scrapy [twisted] CRITICAL: Unhandled error in Deferred:错误

最近刚开始使用爬虫框架scrapy,开始就遇到这么个问题,严重挫伤学习心情,终于耗费一天时间解决这个问题 解决方法: 在安装scrapy的时候下载了pywin32,但是忘记安装这个模块 进入python27目录下,手动安装,可以在命令行使用python python27\scripts\pywin32_postinstall.py -install 之后再运行爬虫程序就ok了

u013358302的专栏 1万+

Error code of Media server (MediaPlayer内核异常码说明)

Error code of Media server HRESULT Description 0x000D0000 The requested operation is pending completion.%0 0x000D0001 The requested operation was aborted by

学习并记录 1万+

jquery回调嵌套的解决方案。promise模式

jQuery回调嵌套的解决方案。其实,jQ已经为我们想好解决方案了,那就是promise模式。下面开始学习。1、deferred 和promise首先,一定要明确和区分2个对象,deferred 和promise,不然后面的学习会混乱的。deferred对象: 创建方法: jQuery.Deferred(); 主要方法:resolve , reject , notify ;

wocaonima332的博客 2497

使用 defer 函数 要注意的几个点

概述 defer 函数大家肯定都用过,它在声明时不会立刻去执行,而是在函数 return 后去执行的。 它的主要应用场景有异常处理、记录日志、清理数据、释放资源 等等。 这篇文章不是分享 defer 的应用场景,而是分享使用 defer 需要注意的点。 咱们先从一道题开始,一起来感受下 ... func calc(index string, a, b int) int { re...

gr32442187do的博客 928

Twisted:exceptions.AssertionError:

出处: http://blog.sina.com.cn/s/blog_704b6af70100py9n.html    13.使用Deferred新功能实现新客户端 代码为: #coding:utf-8 import defer import optparse from twisted.internet import reactor from twisted.internet.protoc

u010565244的专栏 1342

deferred和promise的理解。

deferred对象是一个延迟对象,意思是函数延迟到某个点才开始执行,改变执行状态的方法有两个(成功:resolve和失败:reject),分别对应两种执行回调(成功回调函数:done和失败回调函数fail) 一、deferred和promise的关系和区别 var d = $.deferred(); var p = $.promise(); 1、d对象通过d.resolve()和d...

qq_36470086的博客 3103
上一篇: twisted python学习笔记:三
下一篇: python 中的yield
chjjunking
博客等级 码龄17年 103粉丝 102原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值