Python类内异步函数调用方法报NameError 无法访问变量问题
问题说明
编写Connect类实现币安WebSocket异步获取BTCUSDT交易价格逻辑时,运行代码触发报错:在main异步函数中调用Get2(data_price)时抛出NameError,提示名称'Get2'未定义,同时异步函数内的data_price变量无法正常向外传递。
原始问题代码
class Connect(): global data_price async def main(): client = await AsyncClient.create() bm = BinanceSocketManager(client) # start any sockets here, i.e a trade socket ts = bm.trade_socket('BTCUSDT') # then start receiving messages async with ts as tscm: res = await tscm.recv() data_price = res['p'] print(data_price) data_time = datetime.datetime.now() data_time = datetime.datetime.now() c.execute('''INSERT INTO data VALUES(?,?)''', (data_time, data_price)) connect_db.commit() c.execute('''SELECT * FROM data''') data_display = c.fetchall() print(data_price) Get2(data_price) await client.close_connection() if __name__ == "__main__": loop = asyncio.get_event_loop() loop.run_until_complete(main()) def Get2(data_price): print(data_price)
报错栈信息
Traceback (most recent call last): File "C:\Users\Rhyan\Desktop\Py project\crytpo.py", line 30, in <module> class Connect(): File "C:\Users\Rhyan\Desktop\Py project\crytpo.py", line 57, in Connect loop.run_until_complete(main()) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3568.0_x64__qbz5n2kfra8p0\lib\asyncio\base_events.py", line 647, in run_until_complete return future.result() File "C:\Users\Rhyan\Desktop\Py project\crytpo.py", line 50, in main Get2(data_price) NameError: name 'Get2' is not defined
报错核心原因
- 你把程序入口
if __name__ == "__main__"的执行逻辑直接写在了Connect类的定义块内部,这部分代码会在类加载定义阶段立刻执行,此时Connect类还没完成定义,内部的Get2方法还没完成注册,自然找不到对应名称。 - 类内部定义的普通方法属于类的命名空间,不能像全局函数一样直接裸调用,必须通过类实例引用访问。你在main里直接写
Get2(),Python只会去全局作用域找这个函数,当然匹配不到类内部定义的Get2方法。 - 类的实例方法第一个参数必须传入代表实例本身的
self参数,你写的main、Get2方法都没加这个参数,就算解决了名称找不到的问题,调用时也会触发参数数量不匹配的报错。 - 你在类开头写的
global data_price写法无效:global关键字只能用来声明函数内的变量来自全局作用域,放在类的代码块第一行没有任何作用。类内跨方法传递变量应该用实例属性,不要滥用全局变量。
修复后可运行代码
import asyncio import datetime import sqlite3 from binance import AsyncClient, BinanceSocketManager class Connect: def __init__(self): # 初始化数据库连接,作为实例属性供类内方法共享 self.connect_db = sqlite3.connect('crypto_price.db') self.c = self.connect_db.cursor() self.c.execute('''CREATE TABLE IF NOT EXISTS data (collect_time datetime, btc_price real)''') self.connect_db.commit() self.data_price = None async def main(self): client = await AsyncClient.create() bm = BinanceSocketManager(client) ts = bm.trade_socket('BTCUSDT') async with ts as tscm: res = await tscm.recv() self.data_price = float(res['p']) print(f"实时获取价格: {self.data_price}") data_time = datetime.datetime.now() self.c.execute('''INSERT INTO data VALUES(?,?)''', (data_time, self.data_price)) self.connect_db.commit() self.c.execute('''SELECT * FROM data''') data_display = self.c.fetchall() print(f"数据库存储记录: {data_display}") # 类内部调用自身方法需要通过self引用 self.Get2(self.data_price) await client.close_connection() self.connect_db.close() def Get2(self, data_price): print(f"Get2方法接收到价格参数: {data_price}") if __name__ == "__main__": # 类定义完成后再实例化、启动事件循环 conn_instance = Connect() loop = asyncio.get_event_loop() loop.run_until_complete(conn_instance.main())
修复要点
- 把
if __name__ == "__main__"入口逻辑移到类定义外部,等类完全加载完成后再实例化调用 - 所有实例方法添加
self作为第一个参数,类内部的属性、方法调用统一通过self.xxx的形式访问 - 类内需要跨方法传递的变量(比如价格、数据库连接对象)统一存为实例属性,不要滥用global全局变量
- 数据库连接、WebSocket连接使用完成后显式关闭,避免资源泄漏
内容的提问来源于stack exchange,提问作者Ryan morris
相关产品推荐
相关产品推荐

