Twisted:使用 pyglet-twisted 时如何从 EndPoint 调用 Deferred
Posted
技术标签:
【中文标题】Twisted:使用 pyglet-twisted 时如何从 EndPoint 调用 Deferred【英文标题】:Twisted: How is Deferred called from EndPoint when using pyglet-twisted 【发布时间】:2013-02-07 20:15:42 【问题描述】:以下代码取自 Twisted 关于 AMP 的文档 (link)。当回调被添加到 d 时,会自动添加一个“协议”参数,并且在调用 reactor.run() 时会自动运行 deferred。
def connect():
endpoint = TCP4ClientEndpoint(reactor, "127.0.0.1", 8750)
factory = Factory()
factory.protocol = AMP
return endpoint.connect(factory)
d = connect()
def connected(protocol):
return protocol.callRemote(
RegisterUser,
username=u'alice'
d.addCallback(connected)
reactor.run()
在我的代码中,一切都完全相同,除了我一直在使用 pyglet-twisted (link) 和 cocos2d,所以我不能调用 reactor.run(),因为反应器与申请。
如果我调用 reactor.run(),我会收到一条错误消息,指出反应器已经在运行。
如果我不这样做,deferred 似乎不会被调用。
我一直在尝试使用 reactor.callLater、reactor.callWhenRunning 来调用它,但两者都需要一个参数。传入 None 不起作用。
所以我的问题是,我应该如何在不调用 reactor.run() 的情况下使这个延迟运行。
谢谢!
【问题讨论】:
【参考方案1】:没有一个正在运行的反应器,Twisted 的 API 很少能成功。反应器负责执行 I/O。您必须有一个正在运行的反应器才能建立连接(无论您使用的是端点对象还是其他 API)。
据我所知,pyglet 集成反应器不会自动启动。有些东西必须调用它的run
方法。您的问题表明您没有调用它,所以我很好奇 是什么 调用它。
当我修改您的示例以使其完整且可运行并添加错误报告时,如下所示:
from pygletreactor import install
install()
from twisted.internet import reactor
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.internet.protocol import Factory
from twisted.protocols.amp import AMP
from twisted.python.log import err
def connect():
endpoint = TCP4ClientEndpoint(reactor, "127.0.0.1", 8750)
factory = Factory()
factory.protocol = AMP
return endpoint.connect(factory)
d = connect()
def connected(protocol):
return protocol.callRemote(
RegisterUser,
username=u'alice')
d.addCallback(connected)
d.addErrback(err)
reactor.run()
然后我得到了我期望的行为,即尝试连接然后失败(因为我没有在任何地方运行 AMP 服务器):
Unhandled Error
Traceback (most recent call last):
Failure: twisted.internet.error.ConnectionRefusedError: Connection was refused by other side: 111: Connection refused.
也许您可以将其与您的完整程序进行比较,并找出重要的区别。
【讨论】:
谢谢!我忘了提到我修改了 pyglet 以调用 reactor.run()。我又看了看这个问题,结果发现问题在于 cocos2d 被硬编码以使用 pyglet 的事件循环的方式,所以 pygletreactor 中的循环没有被调用。【参考方案2】:经过更多研究,我发现从endpoint.connect()
返回的deferred
没有被调用的原因是cocos2d的一个错误。
在cocos.director
的底部,其中pyglet.app.event_loop
被分配处理director.event = event_loop.event
行中的导演事件。
这需要改为使用pygletreactor
的eventloop
。所以上面的代码需要改成如下:
import pygletreactor
event_loop = pygletreactor.EventLoop()
director = Director()
director.event = event_loop.event
【讨论】:
以上是关于Twisted:使用 pyglet-twisted 时如何从 EndPoint 调用 Deferred的主要内容,如果未能解决你的问题,请参考以下文章