讲师中心 微信公众号
AI工具推荐 视频效率加速

解决Python异步函数在Jupyter与独立脚本中行为不一致的问题

大枫吖_8525

大枫吖_8525

发布时间:2025-12-13 22:32:13

|

907人浏览过

|

来源于php中文网

原创

解决python异步函数在jupyter与独立脚本中行为不一致的问题

本文旨在解决Python异步函数在使用`asyncio.run()`时,在Jupyter Notebook(`.ipynb`)中运行正常,但在独立Python脚本(`.py`)中表现异常的问题。我们将探讨`asyncio`事件循环的管理机制,特别是`nest_asyncio`的作用,并提供一个健壮的代码结构,确保基于`binance.websockets`的实时数据流在两种环境中都能稳定运行,强调了虚拟环境和模块版本的重要性。

理解异步编程与事件循环

Python的asyncio库提供了一种编写并发代码的方式,通过单线程协作式多任务处理实现非阻塞I/O。在处理网络请求、实时数据流(如WebSocket)等场景时,asyncio能够显著提高程序的效率和响应速度。

asyncio的核心是事件循环(event loop),它负责调度协程(coroutine)的执行。当你调用asyncio.run(main())时,它会启动一个新的事件循环,运行main()协程,并在main()执行完毕后关闭事件循环。

Jupyter Notebook与独立脚本的差异

Jupyter Notebook环境与标准Python脚本在处理asyncio事件循环方面存在关键差异:

立即学习“Python免费学习笔记(深入)”;

  1. Jupyter Notebook: Jupyter环境本身可能已经运行着一个事件循环,或者其内部机制允许更灵活地管理事件循环。当你尝试在已存在事件循环的环境中再次调用asyncio.run()时,通常会遇到错误。nest_asyncio库的作用就是解决这个问题,它允许在已运行的事件循环中嵌套运行新的事件循环,使得asyncio.run()在Jupyter中也能顺利执行。
  2. 独立Python脚本 (.py): 在一个全新的Python进程中运行.py文件时,通常没有预先存在的事件循环。asyncio.run()会创建一个新的事件循环并运行你的协程。理论上,这应该工作正常。如果出现问题,往往与环境配置、依赖版本或代码结构有关。

本教程的场景中,Jupyter Notebook中使用了nest_asyncio.apply(),这使得代码在Notebook中能够无缝运行。但在独立脚本中,即使移除了nest_asyncio.apply(),或者在有它的情况下,代码依然可能在await ts.recv()处阻塞,无法接收数据。这通常不是asyncio本身的问题,而是环境或依赖的特定交互。

构建健壮的实时数据流客户端

为了确保在不同环境中都能稳定运行,特别是针对Binance WebSocket数据流,我们需要一个可靠的代码结构。以下是一个经过验证的实现方案,它封装了异步逻辑,并通过if __name__ == '__main__'保护块确保在脚本直接执行时的正确性。

环境准备:

Browser Setup (No-Root Linux)
Browser Setup (No-Root Linux)

在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...

下载

在开始之前,强烈建议使用Python虚拟环境来管理项目依赖。这可以避免不同项目间的依赖冲突,并确保所有开发者使用相同的库版本。

# 创建虚拟环境
python -m venv venv

# 激活虚拟环境 (Windows)
venv\Scripts\activate
# 激活虚拟环境 (macOS/Linux)
source venv/bin/activate

# 安装所需库
pip install python-binance nest_asyncio

请确保您使用的库版本与已知工作版本一致,例如:

  • Python: 3.12.1
  • python-binance: 1.0.19
  • nest_asyncio: 1.5.8

核心代码实现:

以下代码展示了如何连接Binance WebSocket并接收实时交易数据。为了在独立脚本中稳定运行,我们将异步入口点封装在一个函数中,并在if __name__ == '__main__':块中调用它。

import asyncio
import nest_asyncio
import sys

from binance.client import Client
from binance import BinanceSocketManager

# 在独立脚本中,nest_asyncio通常不是必需的,但在某些复杂环境中或调试时可能有用。
# 如果你确定脚本总是在没有预设事件循环的环境中运行,可以移除此行。
# 但为了与Jupyter环境保持一致性,此处保留。
nest_asyncio.apply()

async def stream_btc_data():
    """
    异步函数,连接Binance WebSocket并持续接收BTCUSDT交易数据。
    """
    client = Client() # 可以在此处传入API_KEY和API_SECRET

    bsm = BinanceSocketManager(client)
    socket = bsm.trade_socket('BTCUSDT')

    try:
        async with socket as ts:
            print("正在连接Binance WebSocket...")
            while True:
                msg = await ts.recv()
                print(f"收到数据: {msg}")
    except asyncio.CancelledError:
        print("数据流已取消。")
    except Exception as e:
        print(f"数据流发生错误: {e}")
    finally:
        await client.close_connection() # 确保关闭客户端连接
        print("Binance WebSocket连接已关闭。")

def run_async_application():
    """
    运行异步主应用,处理事件循环。
    """
    print("启动异步应用...")
    try:
        asyncio.run(stream_btc_data())
    except KeyboardInterrupt:
        print("\n用户中断程序。")
    except RuntimeError as e:
        # 捕获可能由于事件循环已在运行导致的错误
        print(f"运行时错误: {e}")
        print("尝试使用nest_asyncio修复,但如果问题持续,请检查环境。")

if __name__ == '__main__':
    run_async_application()

代码说明:

  1. nest_asyncio.apply(): 尽管在独立脚本中通常不需要,但为了兼容Jupyter Notebook的场景,并避免潜在的“事件循环已在运行”错误,我们保留了它。在纯净的.py环境中,即使没有它,asyncio.run()也会正常工作。
  2. Client(): 初始化Binance客户端。如果需要进行认证操作(如交易),请在此处传入API Key和Secret。对于公共数据流,通常不需要。
  3. BinanceSocketManager: python-binance库提供的WebSocket管理器,简化了连接和数据接收。
  4. bsm.trade_socket('BTCUSDT'): 创建一个用于接收BTCUSDT交易数据的WebSocket连接。
  5. async with socket as ts:: 这是一个异步上下文管理器,它确保WebSocket连接被正确建立和关闭。
  6. while True: msg = await ts.recv(): 循环不断地从WebSocket接收数据。await关键字在这里是关键,它允许程序在等待数据时释放控制权给事件循环,从而执行其他任务(如果存在)。
  7. 错误处理: 添加了try...except...finally块来优雅地处理程序中断 (asyncio.CancelledError 或 KeyboardInterrupt) 和其他潜在的网络或运行时错误,并确保资源(客户端连接)被正确关闭。
  8. run_async_application(): 将asyncio.run()的调用封装在一个函数中。这使得代码结构更清晰。
  9. if __name__ == '__main__':: 这是Python脚本的标准入口点。当脚本作为主程序直接运行时,此块内的代码会被执行。这对于组织代码和避免在模块被导入时意外执行异步函数至关重要。

运行与验证

将上述代码保存为.py文件(例如binance_stream.py),然后在激活的虚拟环境中运行:

python binance_stream.py

您应该会看到程序输出“正在连接Binance WebSocket...”然后开始持续打印接收到的BTCUSDT交易数据。通过按下Ctrl+C可以优雅地中断程序。

注意事项与最佳实践

  • 虚拟环境: 始终使用虚拟环境来隔离项目依赖,避免版本冲突。
  • 依赖版本: 确保python-binance和nest_asyncio的版本与已知稳定版本一致。不兼容的版本可能会导致意外行为。
  • API Key/Secret: 如果需要进行交易或访问私有数据,请务必安全地管理您的Binance API Key和Secret,切勿硬编码在代码中。建议使用环境变量或配置文件。
  • 错误处理与重连: 在生产环境中,应实现更 robust 的错误处理机制,包括网络断开后的自动重连逻辑,以及指数退避策略,以避免频繁重试导致API限制。
  • 日志记录: 使用Python的logging模块来记录程序运行状态、接收到的数据和任何错误信息,以便于调试和监控。
  • 资源清理: 确保在程序退出时关闭所有打开的连接和资源,例如client.close_connection()。

总结

异步编程是处理高并发I/O操作的强大工具。理解asyncio事件循环在不同Python执行环境中的行为差异,并采用健壮的代码结构,是确保异步应用稳定运行的关键。通过遵循本文提供的指南,您可以在Jupyter Notebook和独立Python脚本中都成功地构建和运行基于Binance WebSocket的实时数据流客户端。核心在于正确的环境配置、依赖管理以及对asyncio.run()和事件循环生命周期的深刻理解。

热门AI工具

更多
Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

334

2023.09.25

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

3658

2023.08.10

Golang WebSocket与实时通信开发
Golang WebSocket与实时通信开发

本专题系统讲解 Golang 在 WebSocket 开发中的应用,涵盖 WebSocket 协议、连接管理、消息推送、心跳机制、群聊功能与广播系统的实现。通过构建实际的聊天应用或实时数据推送系统,帮助开发者掌握 如何使用 Golang 构建高效、可靠的实时通信系统,提高并发处理与系统的可扩展性。

175

2025.12.22

PHP WebSocket 实时通信开发
PHP WebSocket 实时通信开发

本专题系统讲解 PHP 在实时通信与长连接场景中的应用实践,涵盖 WebSocket 协议原理、服务端连接管理、消息推送机制、心跳检测、断线重连以及与前端的实时交互实现。通过聊天系统、实时通知等案例,帮助开发者掌握 使用 PHP 构建实时通信与推送服务的完整开发流程,适用于即时消息与高互动性应用场景。

396

2026.01.19

Python WebSocket实时通信与异步服务开发实践
Python WebSocket实时通信与异步服务开发实践

本专题聚焦 Python 在实时通信场景中的开发实践,系统讲解 WebSocket 协议原理、长连接管理、消息推送机制以及异步服务架构设计。内容包括客户端与服务端通信实现、连接稳定性优化、消息队列集成及高并发处理策略。通过完整案例,帮助开发者构建高效稳定的实时通信系统,适用于聊天应用、实时数据推送等场景。

595

2026.03.18

WebSocket 前端开发与实战技巧
WebSocket 前端开发与实战技巧

聚焦 WebSocket 在前端项目中的工程化实践,涵盖原生 JavaScript WebSocket 连接的封装与状态管理、Vue 3 中 WebSocket 的 Composable 封装(useWebSocket)、React 中自定义 Hook 管理连接生命周期、心跳检测(Ping/Pong 定时器)与自动断线重连的实现策略、指数退避重连算法、消息序列化协议(JSON / Protobuf / MessagePack)的选型与性

388

2026.05.25

WebSocket发送和接收数据教程合集
WebSocket发送和接收数据教程合集

本专题整合了WebSocket发送与接收数据教程合集,阅读专题下面的文章了解更多详细内容。

301

2026.05.25

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

0

2026.09.30

LLVM RISC-V参数配置教程
LLVM RISC-V参数配置教程

本专题介绍LLVM对RISC-V基础ISA和扩展的支持方式,涵盖RV32、RV64、标准扩展、实验性扩展、厂商扩展、-menable-experimental-extensions和版本差异。

0

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习

Valgrind支持平台说明
Valgrind支持平台说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn