首页 > 编程问答 >为什么状态不立即切换?

为什么状态不立即切换?

时间:2024-07-25 08:29:53浏览次数:13  
标签:python aiogram

@router.callback_query(StateFilter(FSMPag.forward))
async def collection_f(callback: CallbackQuery, state: FSMContext):
conn = sqlite3.connect('mega_db.db')
cur = conn.cursor()
user_id = callback.from_user.id

cur.execute("""SELECT array FROM users WHERE user_id = ?""", (user_id,))
result = cur.fetchall()[0][0]
numbers = [int(i) for i in result.strip('[]').replace(',', '').split()]

pag_num[user_id] += 1

pathCard = pathlib.Path(dir_p, "cards", f"{pag_card[user_id][int(pag_num[user_id])]}.jpg")
pathCard = FSInputFile(pathCard)
caption=lexicon['collection']

if callback.data == 'forward':
    await state.set_state(FSMPag.forward)
    if pag_num[user_id] + 1 == len(numbers):
        reply_markup = create_pagination_keyboard('backward', f'{pag_num[user_id]+1}/{len(numbers)}')
    else:
        reply_markup = create_pagination_keyboard('backward', f'{pag_num[user_id]+1}/{len(numbers)}', 'forward')
elif callback.data == 'backward':
    await state.set_state(FSMPag.backward)
    if pag_num[user_id] == 0:
        reply_markup = create_pagination_keyboard(f'{pag_num[user_id]+1}/{len(numbers)}')
    else:q
        reply_markup = create_pagination_keyboard('backward', f'{pag_num[user_id]+1}/{len(numbers)}', 'forward')
else:
    pass
await callback.message.edit_media(InputMediaPhoto(media=pathCard, caption=caption), reply_markup=reply_markup)

由于某种原因,机器人识别出所需的回调,但不会立即切换到另一个状态

我尝试重置 if 块中的状态,但仍然没有任何帮助。通过测试,我发现回调被正确识别,并且整个块,如果它与此回调一起工作,只有状态切换不起作用


The reason why your state doesn't change immediately is because await state.set_state() is not blocking . It schedules the state change for the next interaction with the FSM, not within the same handler execution.

Here's how the code execution flows:

  1. Callback received: The collection_f handler is triggered by the callback query.
  2. State check: The StateFilter(FSMPag.forward) ensures the handler only executes if the current state matches.
  3. State set attempt: await state.set_state(FSMPag.forward) is called, BUT this only schedules the state change.
  4. Remaining handler execution: The rest of the collection_f handler continues, including editing the message with the new pagination.
  5. Handler finishes: The execution of collection_f completes WITHOUT the state being actually changed yet.
  6. Next interaction: Only when another update (like a new callback or message) arrives, the FSM middleware will apply the pending state change set by set_state .

Therefore, although you are setting the state within the if callback.data == 'forward' : block, the actual state change only takes effect AFTER the current handler finishes.

Here are two possible solutions:

1. Move state change outside the conditional:

If you want the state to always change to FSMPag.forward regardless of the callback data, simply move await state.set_state(FSMPag.forward) outside the if/elif/else block. This ensures the state is changed before any other logic within the handler.

```python @router.callback_query(StateFilter(FSMPag.forward)) async def collection_f(callback: CallbackQuery, state: FSMContext): # ... your code ...

   await state.set_state(FSMPag.forward) # Move this line here

   if callback.data == 'forward':
       # ... your logic ...
   elif callback.data == 'backward':
       # ... your logic ...
   else:
       pass

   await callback.message.edit_media(...)

```

2. Force state change and re-route:

If you need the state change to happen immediately and influence the current handler's logic, you can force the state update and then re-route the update through the dispatcher:

```python @router.callback_query(StateFilter(FSMPag.forward)) async def collection_f(callback: CallbackQuery, state: FSMContext): # ... your code ...

   if callback.data == 'forward':
       await state.set_state(FSMPag.forward)
       # Force state application
       await state.update_data()
       # Re-route the update for immediate handling
       return await router.forward(callback) 
   elif callback.data == 'backward':
       await state.set_state(FSMPag.backward)
       # Force state application
       await state.update_data()
       # Re-route the update for immediate handling
       return await router.forward(callback) 
   else:
       pass

   await callback.message.edit_media(...)

```

This approach ensures the state is applied immediately and the handler is called again with the new state, allowing you to perform different actions based on the updated state within the same interaction.

标签:python,aiogram
From: 78791047

相关文章

  • Python 中 __get__ 方法的内部原理
    我正在摆弄描述符,结果碰壁了。我以为我可以像使用任何其他方法一样直接调用它,但显然,它似乎不一致或者我遗漏了一些东西。假设我有一个用作描述符的坐标类:|||还有一个Point类,它有2个坐标属性:classCoordinate:def__set_name__(self,owner,name):self._na......
  • 使用带有私钥的云前端生成签名 URL 的问题..使用 Python 3.7 为带有空格的 S3 对象生
    我在使用Python3.7为S3对象生成签名URL时遇到问题。具体来说,键中带有空格的对象的URL会导致“访问被拒绝”错误,而没有空格的对象的URL通常工作正常。但是,并非所有不带空格的对象都能正常工作,带空格的对象始终会失败。fromdatetimeimportdatetime,timedeltaimpo......
  • 有没有更好的方法来在存储库中的一组 python 程序之间共享公共代码
    当我想要快速、轻松地做许多不同的事情时,我会选择Python-即我总是会得到许多Python“程序”-例如一组脚本-或者如果我正在玩一些东西,一堆测试程序等-即始终是许多不同程序的松散集合。但是,我会分享某些内容。例如,如果我正在使用AI-我可能有30个左右完全不相......
  • 如何在Python中从两个不同长度的列表创建DataFrame,为第二个列表中的每个值重复第一个
    我是一个超级初学者,所以请耐心等待。我觉得这应该很容易,但我无法弄清楚。我不确定是否应该创建两个列表,然后将它们组合起来,或者是否有办法以这种方式直接创建DataFrame。我需要一列包含这些值:df=pd.DataFrame({'x1':np.linspace(-2.47,2.69,num=101)})然后我将值A......
  • Python multiprocessing.connection.Connection 的行为不符合规范
    根据python规范,recv()pythonConnection的方法,(从multiprocessing.Pipe()返回,当管道为空且管道的另一端关闭时抛出EOFError(这里参考:https://docs.python.org/3.9/library/multiprocessing.html#multiprocessing.connection.Connection.re......
  • 使用 python Flask 发送邮件中的图像
    我想发送一封包含html代码和图像的电子邮件但在gmail中它说图像已附加,我不想要这样,我只想要电子邮件正文中的图像。html_content=f"<imgsrc="cid:banner"alt=""style="width:80%;">"msg=MIMEMultipart('related')html_part=MIMEText(html_c......
  • 在 python requests modul 中,如何检查页面是否使用“POST”方法或“GET”方法
    如何使用python“requests”模块检查页面是否使用“GET”方法或“POST”方法。我期望输出为True或False,或者GET或Post预期代码:importrequestsurl=f"www.get_example.com"response=requests.get(url)ifresponse.check_get==True:print("get")你......
  • VS Code Python - 如果括号(括号、大括号等)未关闭,内联建议不起作用
    我遇到的问题是,当我在未闭合的括号或方括号“内部”开始变量名称时,VSCode将不会显示任何建议。但是,如果在键入变量名称之前闭合括号,则建议效果很好。如果我可以避免它,我宁愿不将自动完成括号关闭设置为True也不使用TabOut扩展。第一个屏幕截图显示建议在闭括号/方......
  • 在 Azure 上部署代码时使用 Python 的多处理模块是否有意义?
    我们的团队在Azure机器学习(AML)上部署了一个Python脚本来处理存储在Azure存储帐户上的文件。我们的管道由一个ForEach活动组成,该活动调用每个或列出的文件的Python脚本。从Azure数据工厂(ADF)运行它会触发多个单独的管道同时运行......
  • 我已成功安装 pypdf2 但无法将其导入到我的 python 文件中
    我已经成功安装了pypdf2模块,但在导入它时,我发现该模块丢失了。我尝试使用fromPyPDF2importPdfReader导入,但它不起作用此问题的各种解决方案是什么?在尝试导入PyPDF2时遇到问题。以下是可能导致此问题的一些常见原因和解决方案:安......