Django异步上下文报错:“不能从异步上下文调用”,Telegram Bot如何修复?
Django异步Telegram Bot调用send_message报错的修复方案
问题重现
我在Django中开发Telegram Bot时使用异步方法,代码如下:
@dp.message(Command('habits')) async def handle_habits(message: types.Message): chat_id = message.chat.id profile = await TelegramProfile.objects.aget(chat_id=chat_id) user = profile.user await bot.send_message(chat_id, text=f'user - {user}')
执行最后一行时触发错误:You cannot call this from an async context - use a thread or sync_to_async。
错误原因
当前使用的bot实例是同步版本,其send_message方法是同步阻塞调用,无法直接在Django的异步上下文环境中执行。
修复方法
方法1:用sync_to_async包装同步方法
借助Django提供的asgiref.sync.sync_to_async工具,将同步的send_message方法转为异步调用:
from asgiref.sync import sync_to_async @dp.message(Command('habits')) async def handle_habits(message: types.Message): chat_id = message.chat.id profile = await TelegramProfile.objects.aget(chat_id=chat_id) user = profile.user # 包装同步方法后异步调用 await sync_to_async(bot.send_message)(chat_id, text=f'user - {user}')
方法2:切换为异步版Telegram Bot库
如果使用的是python-telegram-bot库,直接升级到支持异步的版本(v13及以上),使用异步API编写代码,避免同步异步混合调用的问题:
from telegram import Update from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes # 初始化异步Bot应用 application = ApplicationBuilder().token("你的Bot令牌").build() async def handle_habits(update: Update, context: ContextTypes.DEFAULT_TYPE): chat_id = update.effective_chat.id profile = await TelegramProfile.objects.aget(chat_id=chat_id) user = profile.user # 直接调用异步send_message方法 await context.bot.send_message(chat_id=chat_id, text=f'user - {user}') # 注册命令处理器 application.add_handler(CommandHandler("habits", handle_habits)) # 启动Bot application.run_polling()
注:原代码中字符串格式错误
text=user - {user}'已修正为text=f'user - {user}',使用f-string实现变量插值。
内容的提问来源于stack exchange,提问作者narcel
相关产品推荐
相关产品推荐

