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

如何在Python 3中处理回调及自定义HTTP LISTEN的非阻塞调用?

哈喽!我来逐个给你解答这两个问题:

1. 如何在Python 3中处理回调(callback)?

回调说白了就是把一个函数当成参数传给另一个函数,让它在某个特定时机自动触发执行。Python对这种模式支持得特别顺手,下面给你举几个常见场景的例子:

基础同步回调

最直接的用法就是简单的函数传递,比如你写一个处理数据的函数,把回调函数传进去,等数据处理完就触发它:

def process_data(data, on_complete):
    print(f"正在处理数据: {data}")
    # 模拟耗时操作
    import time
    time.sleep(2)
    # 处理完成后触发回调
    on_complete(f"处理结果: {data.upper()}")

def handle_result(result):
    print(f"收到回调结果: {result}")

# 调用时传入回调函数
process_data("hello world", handle_result)

异步场景下的回调

如果是异步IO场景(比如用asyncio),回调也可以配合协程使用,或者用add_done_callback方法处理异步任务的结果:

import asyncio

async def async_process_data(data):
    print(f"异步处理数据: {data}")
    await asyncio.sleep(2)
    return f"异步处理结果: {data.upper()}"

def async_callback(future):
    print(f"收到异步回调结果: {future.result()}")

async def main():
    task = asyncio.create_task(async_process_data("hello async"))
    # 给任务添加回调
    task.add_done_callback(async_callback)
    # 继续执行其他逻辑
    print("主线程可以做其他事情...")
    await task

asyncio.run(main())

类中的回调

如果是面向对象的代码,也可以把类的方法作为回调传递:

class DataProcessor:
    def process(self, data, callback):
        print(f"类方法处理数据: {data}")
        callback(f"类处理结果: {data * 2}")

class ResultHandler:
    def handle(self, result):
        print(f"类方法接收回调: {result}")

processor = DataProcessor()
handler = ResultHandler()
processor.process(123, handler.handle)

2. 如何调用自定义HTTP动词LISTEN并避免阻塞主代码?

你的场景是一个阻塞的LISTEN请求,服务器会持续推送更新,这时候要让主代码不被卡住,有两种主流方案:多线程或者异步HTTP客户端,下面分别给出具体实现:

方案一:用多线程把监听逻辑放到子线程

这种方法最简单,把阻塞的LISTEN请求放到单独的线程里,主线程该干嘛干嘛:

import requests
import threading

def listen_for_updates(url):
    try:
        # 发送LISTEN请求,stream=True表示开启流式响应(关键!)
        with requests.request("LISTEN", url, stream=True) as response:
            response.raise_for_status()
            # 逐行读取服务器推送的内容(因为每次更新是一段独立的JSON)
            for line in response.iter_lines():
                if line:
                    # 解析JSON
                    import json
                    update = json.loads(line)
                    print(f"收到资源更新: {update}")
                    # 这里可以加你自己的处理逻辑,比如触发其他回调
    except Exception as e:
        print(f"监听出错: {e}")
        # 可选:添加重连逻辑,比如休眠几秒后重新发起请求

def main():
    listen_url = "http://<IP-Address>:<Port>/resource"
    # 创建并启动子线程,daemon=True让子线程随主线程退出而结束
    listen_thread = threading.Thread(target=listen_for_updates, args=(listen_url,), daemon=True)
    listen_thread.start()

    # 主线程继续执行其他逻辑
    print("主线程正在执行其他任务...")
    while True:
        # 模拟主任务持续运行
        import time
        time.sleep(3)
        print("主线程还在工作...")

if __name__ == "__main__":
    main()

方案二:用异步HTTP客户端(aiohttp)实现非阻塞监听

如果你的项目本身是异步架构,用aiohttp会更优雅,不需要额外线程,完全基于异步IO:

import aiohttp
import asyncio
import json

async def listen_for_updates(url):
    try:
        async with aiohttp.ClientSession() as session:
            # 发送LISTEN请求,timeout=None表示不设置超时(因为是长期监听)
            async with session.request("LISTEN", url, timeout=None) as response:
                response.raise_for_status()
                # 逐块读取流式响应
                async for line in response.content:
                    if line:
                        update = json.loads(line.decode('utf-8'))
                        print(f"收到资源更新: {update}")
    except Exception as e:
        print(f"监听出错: {e}")
        # 可选:添加重连逻辑

async def main():
    listen_url = "http://<IP-Address>:<Port>/resource"
    # 创建监听任务
    listen_task = asyncio.create_task(listen_for_updates(listen_url))

    # 异步主协程执行其他逻辑
    print("异步主协程正在执行其他任务...")
    while True:
        await asyncio.sleep(3)
        print("异步主协程还在工作...")

    # 如果需要停止监听,可以调用 listen_task.cancel()

asyncio.run(main())

注意事项

  • 不管用哪种方案,都要做好异常处理(比如服务器断开、网络波动),可以在监听函数里加自动重连的逻辑
  • 服务器返回的每一行是独立的JSON,一定要逐行解析,别把多行混在一起,不然会解析出错

内容的提问来源于stack exchange,提问作者Michael Westen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:08:02