在aiogram中运行状态机报错:AttributeError: 'NoneType'无'current_state'属性
问题描述
开发Telegram Bot时使用aiogram库,启动Bot的同时运行check_time异步函数,该函数通过无限循环调用intermediary,当满足时间条件时调用analysis启动状态机,触发如下错误:
File "E:\Profile\Desktop\Projects\Python\Productivity control\src\handlers\analysis.py", line 12, in check_time await intermediate() File "E:\Profile\Desktop\Projects\Python\Productivity control\src\handlers\analysis.py", line 29, in intermediary await asyncio.gather(*tasks) File "E:\Profile\Desktop\Projects\Python\Productivity control\src\handlers\analysis.py", line 35, in analysis await Days.value_of_day.set() File "C:\Users\serg\AppData\Local\Programs\Python\Python38-32\lib\site-packages\aiogram\dispatcher\filters\state.py", line 56, in set state = Dispatcher.get_current().current_state() AttributeError: 'NoneType' object has no attribute 'current_state'
相关代码:check_time与intermediary实现:
async def check_time(): while True: await asyncio.sleep(60) await intermediary() async def intermediary(): times = db.get_time_of_day() now = datetime.datetime.now() minute = str(now.minute) hour = str(now.hour) if len(str(now.minute)) == 1: minute = '0' + str(now.minute) if len(str(now.hour)) == 1: hour = '0' + str(hour) for time in times: if str(time[0]) == hour + minute: tasks = [] tasks.append(asyncio.create_task(check_time())) tasks.append(asyncio.create_task(analysis(time[1]))) await asyncio.gather(*tasks) print('all') async def analysis(tg): await Days.value_of_day.set()
状态机类:
class Days(StatesGroup): value_of_day = State()
数据库查询方法:
def get_time_of_day(self): with self.connection: time = self.cursor.execute(f"select time_of_day, tg_id from users").fetchall() return time
问题根源
- 上下文缺失:
check_time是独立启动的异步任务,不在aiogram Dispatcher的请求处理上下文内,调用Days.value_of_day.set()时,Dispatcher.get_current()无法获取到有效实例,返回None触发错误。 - 会话未绑定:状态机是与用户会话绑定的,
analysis函数拿到了用户tg_id但未用来指定对应的会话,无法正确关联状态。
解决步骤
绑定Dispatcher上下文启动任务
在Bot启动代码中,通过Dispatcher的loop创建check_time任务,确保任务运行在正确的上下文环境中:if __name__ == '__main__': from aiogram import executor # 假设dp是你的Dispatcher实例 dp.loop.create_task(check_time()) executor.start_polling(dp, skip_updates=True)修改
analysis函数,指定用户会话
通过用户tg_id获取对应状态对象,再设置状态:async def analysis(tg_id, dispatcher): # 获取指定用户的状态实例 state = dispatcher.current_state(chat=tg_id, user=tg_id) await state.set_state(Days.value_of_day.state)修正
intermediary的任务逻辑
无需重复创建check_time任务(原任务已在无限循环),直接调用analysis并传入Dispatcher实例:# 导入你的Dispatcher实例,根据实际路径调整 from src.main import dp async def intermediary(): times = db.get_time_of_day() # 简化时间格式化 current_time = datetime.datetime.now().strftime("%H%M") for time in times: if str(time[0]) == current_time: await analysis(time[1], dp) print('all')
内容的提问来源于stack exchange,提问作者Pavel
相关产品推荐
相关产品推荐

