如何在asyncio上运行Twisted客户端?代码卡顿问题求助
问题描述
我从Twisted官方文档借鉴了一段客户端代码,正在开发需兼容Twisted的asyncio项目,尝试用asyncio运行该代码,但程序始终卡在res = await d.asFuture(asyncio.get_event_loop())这一行。代码如下:
import asyncio from twisted.internet import asyncioreactor from twisted.web.client import Agent from twisted.web.http_headers import Headers asyncioreactor.install() async def request(): agent = Agent(asyncioreactor.AsyncioSelectorReactor) d = agent.request( b'GET', b'http://httpbin.com/anything', Headers({'User-Agent': ['Twisted Web Client Example']}), None) def cbResponse(ignored): print('Response received') d.addCallback(cbResponse) def cbShutdown(ignored): asyncioreactor.AsyncioSelectorReactor.stop() d.addBoth(cbShutdown) print("This is where it always get stuck") res = await d.asFuture(asyncio.get_event_loop()) print("SUCCESSS!!!!") if __name__ == "__main__": asyncio.run(request())
执行python request.py后无后续输出,请问用asyncio运行Twisted客户端是否可行?该如何解决卡顿问题?
解决方案
完全可行,你的代码存在两个关键问题:
- 错误使用Reactor类而非实例:你直接传入
asyncioreactor.AsyncioSelectorReactor类给Agent,而不是已经安装好的reactor实例。Twisted的Agent需要绑定到运行中的reactor实例,而非类本身。 - 错误调用reactor的stop方法:你调用的是
asyncioreactor.AsyncioSelectorReactor.stop()类方法,而非实例的stop方法,这无法正确停止reactor。
修正后的代码如下:
import asyncio from twisted.internet import asyncioreactor, reactor from twisted.web.client import Agent from twisted.web.http_headers import Headers asyncioreactor.install() async def request(): # 使用已安装好的reactor实例,而非类 agent = Agent(reactor) d = agent.request( b'GET', b'http://httpbin.com/anything', Headers({'User-Agent': ['Twisted Web Client Example']}), None) def cbResponse(response): print('Response received') return response d.addCallback(cbResponse) def cbShutdown(_): # 调用实例的stop方法 reactor.stop() d.addBoth(cbShutdown) print("Waiting for response...") res = await d.asFuture(asyncio.get_event_loop()) print("SUCCESSS!!!!") return res if __name__ == "__main__": # 启动reactor并运行异步任务 asyncio.run(request())
额外注意点:
- 安装asyncioreactor后,直接使用
twisted.internet.reactor即可获取当前运行的reactor实例,无需手动创建。 asFuture方法需要传入正确的asyncio事件循环,这里asyncio.get_event_loop()在asyncio.run上下文里是正确的。- 回调函数里最好返回response,这样await后能拿到响应对象做后续处理。
内容的提问来源于stack exchange,提问作者Ruben Quinones
相关产品推荐
相关产品推荐

