使用Python Twisted Web Client读取API响应失败求助
解决Twisted Web Client中自定义Protocol未被调用的问题
看起来你的代码里有几个小问题导致BeginningPrinter协议完全没触发,我帮你逐个排查并修复:
1. 核心问题:缺少pformat的导入
你的cbRequest函数里用了pformat打印响应头,但没有从pprint模块导入它。这会导致运行时直接抛出NameError,程序会跳过后面的response.deliverBody调用——这就是自定义协议完全没执行的关键原因!
2. 次要问题:请求URL的前导空格
你的请求URL是b' http://127.0.0.1:5000/receiveKeyCode',开头多了一个空格。虽然Twisted可能会兼容这个格式,但严格来说这是无效的URL,可能引发潜在的请求异常,建议去掉。
3. 程序退出问题:Reactor未正确停止
cbShutdown里注释掉了reactor.stop(),会导致程序处理完响应后一直挂起,无法正常退出。
修复后的完整代码
我把这些问题都修正了,还优化了输出可读性:
from io import BytesIO import json from pprint import pformat # 新增pformat的导入 from twisted.internet import reactor from twisted.web.client import Agent from twisted.web.http_headers import Headers from twisted.internet.defer import Deferred from twisted.internet.protocol import Protocol from twisted.web.client import FileBodyProducer agent = Agent(reactor) class BeginningPrinter(Protocol): def __init__(self, finished): self.finished = finished self.remaining = 1024 * 10 print('✅ BeginningPrinter已初始化') def dataReceived(self, bytes): print('\n📥 收到响应数据:') if self.remaining: display = bytes[:self.remaining] # 解码成UTF-8字符串,更易读JSON或错误消息 print(f'显示{len(display)}字节内容:') print(display.decode('utf-8')) self.remaining -= len(display) def connectionLost(self, reason): print(f'\n🔚 响应接收完成:{reason.getErrorMessage()}') self.finished.callback(None) TESTDATA = { "keySequence": "2019-07-14" } jsonData = json.dumps(TESTDATA) body = BytesIO(jsonData.encode('utf-8')) body = FileBodyProducer(body) headerDict = { 'User-Agent': ['test'], 'Content-Type': ['application/json'], 'APIGUID': ['ForTesting'] } header = Headers(headerDict) # 去掉URL开头的空格 d = agent.request(b'POST', b'http://127.0.0.1:5000/receiveKeyCode', header, body) def cbRequest(response): print(f'响应版本: {response.version}') # 把phrase解码成字符串,避免b'UNAUTHORIZED'这种字节输出 print(f'响应码: {response.code} | 描述 : {response.phrase.decode("utf-8")}') print('响应头:') print(pformat(list(response.headers.getAllRawHeaders()))) print(f'响应长度: {response.length}') finished = Deferred() response.deliverBody(BeginningPrinter(finished)) return finished d.addCallback(cbRequest) def cbShutdown(ignored): reactor.stop() # 恢复reactor停止逻辑,保证程序正常退出 d.addBoth(cbShutdown) reactor.run()
优化说明
- 给
BeginningPrinter加了更明确的初始化提示,方便你确认协议是否被正确创建 - 将字节数据解码为UTF-8字符串,不管是错误消息还是JSON响应都能直接阅读
- 对
response.phrase也做了解码,输出更友好的文本格式
修改后你应该能看到BeginningPrinter的完整日志输出,以及接口返回的具体内容了。
内容的提问来源于stack exchange,提问作者Swatcat
相关产品推荐
相关产品推荐

