在 Streamlit 中处理后台任务的问题

问题描述 投票:0回答:1

我正在构建一个 Streamlit 应用程序,当单击“push 1”时,该应用程序会在后台运行一项耗时的任务。

但是,我面临执行流程的问题: 如果我使用“push 1”而不是“push 2”,“push 2”给出的结果类似于“push 1”+“push 2” 如果我使用“push 2”则结果正确。

我尝试了不同的键。看来不行 没有“while True”它可以工作,但我需要循环从设备实时获取数据

这可能是什么原因?以及如何修复它?

这是我正在使用的代码的简化版本:

import streamlit as st
import time


if st.button('📐 Push 1 ', key=1):
    with st.spinner("wait Push 1"):
        time.sleep(1)
        st.success('Push 1')

if st.button('🎬 Push 2', key=2):
    st.success('Push 2')

while True:
    pass

python python-3.x streamlit
1个回答
0
投票

好吧,看来我可以帮到你!

我目前正在创建一个 Streamlit 应用程序,它应该能够监视无限期运行的独立 Python 脚本。代码如下,但请允许我指出一个问题。

据我对 Streamlit 的了解,它是一个用 Flask 构建并使用 React 渲染的框架。所以它基本上是一座桥梁。但请注意,这个桥是完全程序化的,这意味着它的想法是从上到下执行每个 Streamlit 应用程序(如果我错了,请告诉我)。因此,如果代码中有任何点不是线性执行的,整个应用程序将停留在该特定行上,直到完成。那么你猜怎么着?对于我们的目的而言,这是一个主要问题。我们将我们的问题描述为非程序性的(例如永远运行的机器人或不断抛出结果的昂贵计算)。所以我们的问题类型并不完全是 Streamlit 想要解决的问题;它更多的是用于呈现简单的线性应用程序。我可能完全错了;我不是 Streamlit 专家。但结论是,实际上 Streamlit 的构建方式允许我们创建自己的前端,并且确实可以在后台执行!因此,即使它不是“完全是 Streamlit”,您也可以创建自己的 React 组件,并且这个 JS 组件完全能够运行后台活动!

因此,它并不完全是用Python编写的;您仍然可以通过创建 React 组件来实现后台活动的“正确”行为。

我对这一切的结论是什么?是的,我能够运行一个不会阻塞 Streamlit 主循环的活动,如下所示,但它还不够正确,因为当我们调用 asyncio.run(run_task()) 时,代码将被卡住。我没有找到避免这种情况的方法,但是如果你创建一个 React 组件,它将在前端执行并返回到主循环。

所以下面的代码是错误的,但它比您所展示的要好,因为这里的代码可以工作,但不完全正确,但它演示了为什么创建 React 组件是正确的解决方案。

但是你可能会问,为什么我要将整个后台任务重写为 JS 以适应 Streamlit 方式? IDK,但我想这是唯一的解决方案。

我喜欢 Streamlit!它解决了我必须做的很多应用程序,但它仍然有限。

对于这种应用程序(运行后台任务),我强烈推荐 Flutter!因为这个框架的性质完全符合这个需求。而且它很容易学习,并且有一个庞大的生态系统。

#!/usr/bin/env python
# Streamlit, version 1.33.0
# Python 3.10.11
import os
import streamlit as st
import asyncio

# Define variable to track the tasks
if 'keep_running' not in st.session_state:
    st.session_state.keep_running = False

# Any asyncronous task
async def run_task():
    while st.session_state.keep_running:
        print('Background Task running...')
        await asyncio.sleep(1)

# Streamlit
def main():
    st.title('Background Task with streamlit')

    st.session_state.keep_running = st.toggle('Activate Background Tasks', key='toggle_bot')

    nome = st.text_input('Enter your name', key='name')

    st.write(f'Hello {nome}!')

    if st.session_state.keep_running:
        st.toast('Running background Tasks', icon='🤖')
        # THE CODE IS STUCK HERE
        asyncio.run(run_task())
    else:
        os.system('cls' if os.name == 'nt' else 'clear')
        st.write('Stop background Tasks.')

# Execute Streamlit
if __name__ == "__main__":
    main()

© www.soinside.com 2019 - 2024. All rights reserved.