You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:22:20