FastAPI FSM 不适用于我使用 FastAPI 运行 aiogram 的情况
在本文中,我们将介绍 FastAPI FSM 在使用 FastAPI 运行 aiogram 时的问题以及解决方法。FastAPI 是一个基于 Python 的高性能 Web 框架,而 aiogram 则是一个用于构建 Telegram 机器人的库。然而,当我们尝试在 FastAPI 项目中使用 aiogram 时,发现 FastAPI 的 FSM(有限状态机)在运行时并不起作用,导致状态切换失效。本文将详细讨论这个问题,并提供一种解决方案。
阅读更多:FastAPI 教程
问题描述
在使用 FastAPI 和 aiogram 的过程中,我们经常会遇到需要使用有限状态机(FSM)的情况。FSM 可以帮助我们管理用户与机器人的会话状态,从而实现更复杂的交互逻辑。然而,在将 aiogram 集成到 FastAPI 项目中时,我们发现 FSM 并不起作用,状态切换不起效果。
探究原因
经过调查,我们发现这个问题是由于 FastAPI 和 aiogram 在处理请求和响应时的机制不同所导致的。FastAPI 采用异步的方式处理请求和响应,而 aiogram 则是基于同步的方式运行。这样就造成了在使用 FSM 进行状态切换时的冲突,导致 FSM 功能失效。
解决方案
为了解决这个问题,我们可以使用一个叫做 “aiogram.contrib.middlewares.fastapi” 的中间件库来集成 FastAPI 和 aiogram。该库提供了一个名为 “AiogramApp” 的类,用于处理 aiogram 和 FastAPI 的集成。使用这个库可以使 FSM 功能在 FastAPI 中正常工作。
首先,在项目中安装 “aiogram.contrib.middlewares.fastapi”:
pip install aiogram[fastapi]
然后,在项目中引入所需的依赖:
from aiogram import Bot
from aiogram.contrib.middlewares.fastapi import InvincibleMiddleware
from aiogram.dispatcher import Dispatcher
from aiogram.types import BotCommand
from aiogram.contrib.middlewares.fastapi import RequestContextMiddleware
from fastapi import FastAPI
app = FastAPI()
TOKEN = "YOUR_TELEGRAM_BOT_TOKEN"
bot = Bot(token=TOKEN)
dp = Dispatcher(bot)
接下来,我们需要在 FastAPI 中注册中间件,使其可以正常工作:
@app.on_event("startup")
async def on_startup():
# 为 FastAPI 和 aiogram 注册中间件
app.add_middleware(InvincibleMiddleware, dp=dp)
app.add_middleware(RequestContextMiddleware, dp=dp)
@app.on_event("shutdown")
async def on_shutdown():
# 关闭 aiogram 的事件循环
await dp.storage.close()
await dp.storage.wait_closed()
await bot.close()
@app.get("/set_commands")
async def set_commands():
# 设置机器人的命令
commands = [
BotCommand(command="/start", description="Start the bot"),
BotCommand(command="/help", description="Get help"),
]
await bot.set_my_commands(commands)
return {"message": "Commands set successfully."}
现在,我们可以根据自己的需求,通过 aiogram 的方式来实现有限状态机的功能:
from aiogram import types
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
class Registration(StatesGroup):
name = State()
age = State()
gender = State()
@dp.message_handler(commands=['start'])
async def cmd_start(message: types.Message, state: FSMContext):
await message.reply("Welcome! What's your name?")
await Registration.name.set()
@dp.message_handler(state=Registration.name)
async def process_name(message: types.Message, state: FSMContext):
async with state.proxy() as data:
data['name'] = message.text
await message.reply("How old are you?")
await Registration.next()
@dp.message_handler(state=Registration.age)
async def process_age(message: types.Message, state: FSMContext):
async with state.proxy() as data:
data['age'] = message.text
await message.reply("What's your gender?")
await Registration.next()
@dp.message_handler(state=Registration.gender)
async def process_gender(message: types.Message, state: FSMContext):
async with state.proxy() as data:
data['gender'] = message.text
await state.finish()
await message.reply("Thank you for the information! Registration completed.")
通过以上代码,我们可以实现一个简单的用户注册功能,用户需要依次输入姓名、年龄和性别。使用 FSM 可以很方便地管理用户的会话状态,从而实现复杂的功能。
总结
通过使用 “aiogram.contrib.middlewares.fastapi” 中间件库,我们可以在使用 FastAPI 运行 aiogram 时正常使用 FSM 功能。解决了在集成 FastAPI 和 aiogram 时遇到的 FSM 不工作的问题。现在,我们可以轻松地构建复杂的 Telegram 机器人,并充分利用 FastAPI 的高性能特性。