aiogram开发Telegram Bot时JSON写入冲突及__aenter__报错求解
报错根因
AttributeError: __aenter__报错触发原因:Python内置的open()是同步上下文管理器,未实现异步上下文协议要求的__aenter__、__aexit__方法,无法配合async with语法使用。- 原有逻辑的额外隐患:多用户并发触发写入时会产生竞态条件,出现写操作互相覆盖、JSON文件内容损坏的问题;同步IO直接运行在异步协程中还会阻塞事件循环,导致机器人暂时无法响应其他用户请求。
修复方案
前置依赖安装
先安装异步文件操作依赖:
pip install aiofiles
完整实现代码
核心逻辑两点:用aiofiles做非阻塞的异步文件读写,加全局异步锁让所有写请求排队执行,从根源避免并发冲突。
import json import aiofiles from asyncio import Lock from aiogram import types from aiogram.dispatcher import FSMContext # 全局配置 DATA_SAVE_PATH = "D:/Code/data.json" # 全局异步写入锁,同一时间仅允许一个协程执行文件写操作 file_write_lock = Lock() async def load_abit_class(message: types.Message, state: FSMContext): async with state.proxy() as abit_data: abit_data['class'] = int(message.text) # 抢锁,锁释放前其他写入请求会等待 async with file_write_lock: # 异步打开文件,不会阻塞事件循环 async with aiofiles.open(DATA_SAVE_PATH, 'w', encoding='utf-8') as f: # 序列化为JSON字符串,指定ensure_ascii=False避免中文乱码 json_content = json.dumps(abit_data, ensure_ascii=False, indent=2) await f.write(json_content) await state.finish()
补充说明
- 如果你是多进程部署机器人(比如启动了多个服务worker),协程锁无法跨进程生效,需要替换为跨进程的文件锁,比如使用
filelock库的AsyncFileLock实现。 - 如果后续数据量变大、读写频率变高,建议直接替换为SQLite这类轻量嵌入式数据库,原生支持事务并发控制,不需要手动维护锁逻辑,稳定性远高于手动读写JSON文件。
内容的提问来源于stack exchange,提问作者MC_Vovi
相关产品推荐
相关产品推荐

