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

新线程运行async异步函数卡在asyncio.new_event_loop如何解决

问题根因
  • 卡在asyncio.new_event_loop()是跨线程创建事件循环的兼容性问题:
    • 主线程直接调用时,Python启动流程已经为主线程预初始化了适配当前系统的事件循环资源,不会触发资源申请死锁
    • 子线程中直接创建事件循环时,Windows系统默认的ProactorEventLoop会尝试申请仅主线程可访问的IOCP、信号处理相关资源,直接触发卡死;部分Linux环境下高版本websockets库提前绑定主线程事件循环钩子时,也会出现同类问题
    • 原代码还存在两个隐性问题:一是logger未定义,运行到异常分支会直接抛错;二是子线程设置为daemon=True,如果主线程启动子线程后没有阻塞逻辑,会直接退出杀死子线程,即使事件循环启动成功也无法持续运行
修复方法

在子线程入口函数最开头,手动指定适配子线程运行的事件循环策略,补全缺失的依赖,同时给主线程加阻塞等待逻辑:

import asyncio
import json
import threading
import time
import logging
import websockets.client
import websockets.exceptions

# 补全logger配置
logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger(__name__)

ws_url = "wss://phemex.com/ws/"
sub_orderbook = {"id": 1234, "method": "orderbook.subscribe", "params": ["BTCUSD"]}


async def orderbook():
    while True:
        try:
            async for websocket in websockets.client.connect(ws_url, close_timeout=0.001):
                try:
                    
                    await websocket.send(json.dumps(sub_orderbook))
                    while True:
                        msg = await websocket.recv()
                        print(msg)
                        obj = json.loads(msg)
                        if isinstance(obj, dict) and obj.get('event') == 'ping':
                            await websocket.send(json.dumps({'event': 'pong'}))
                
                except websockets.exceptions.ConnectionClosed as cc:
                    logger.warning(f'Connection at {ws_url} closed: {cc}')
                    continue
        except Exception:
            logger.warning(f'Restarting after unexpected exception:', exc_info=True)

def orderbook_callback():
    import sys
    # 子线程启动前先设置适配跨线程运行的事件循环策略
    if sys.platform == 'win32':
        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
    print("Hi")
    loop = asyncio.new_event_loop()
    print("bye")
    asyncio.set_event_loop(loop)
    try:
        loop.run_until_complete(orderbook())
    finally:
        loop.close()

_thread = threading.Thread(target=orderbook_callback, daemon=True)
_thread.start()

# 主线程加阻塞,避免直接退出
while True:
    time.sleep(3600)
验证说明
  • 运行后会先打印Hi再打印bye,随后正常输出websocket返回的订单簿数据
  • 如果是非Windows环境,不需要额外设置事件循环策略,只要补全logger配置和主线程阻塞逻辑即可正常运行

内容的提问来源于stack exchange,提问作者siad houssam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 02:39:50