解决Streamlit应用中stqdm中断导致的冻结问题

花韻仙語

花韻仙語

2025-09-13

777人浏览

原创

解决Streamlit应用中stqdm中断导致的冻结问题

当在Streamlit应用中使用stqdm.pandas.progress_apply进行长时间操作时,若应用被意外中断,可能导致下次运行时冻结。本文将深入探讨此问题,并提供一个有效的解决方案:通过设置stqdm.set_lock(RLock())来避免因锁定机制冲突而引发的应用崩溃,尤其在Windows环境下此问题更为常见,确保应用稳定运行。

问题现象与影响

在streamlit应用中,开发者经常需要处理大量数据,并希望通过进度条向用户展示操作进度。stqdm库提供了一个极佳的解决方案,它能将tqdm的进度条无缝集成到streamlit界面中,尤其是在与pandas的apply或progress_apply方法结合使用时。然而,一个常见且令人头疼的问题是,当使用stqdm.pandas.progress_apply执行耗时操作时,如果用户在操作完成前关闭浏览器标签页、刷新应用或streamlit服务意外中断,应用程序可能会在下次运行时陷入无限循环或完全冻结,唯一的解决办法往往是重启streamlit服务。

考虑以下代码示例,它模拟了一个耗时的数据帧操作:

import streamlit as st
from time import sleep
import pandas as pd
import numpy as np
from stqdm import stqdm

def something_heavy(x):
    """模拟一个耗时操作"""
    sleep(1) # 暂停1秒
    return x * 100

# 创建一个示例DataFrame
df = pd.DataFrame(np.random.randint(0, 100, size=(10, 2)), columns=list('AB'))

# 注册stqdm到pandas,并显示进度条
stqdm.pandas(desc='正在执行繁重操作')
df['C'] = df.progress_apply(lambda row: something_heavy(row['A']), axis=1)
st.write(df)

当上述代码运行时,进度条会正常显示。但如果在df.progress_apply完成之前,Streamlit应用被中断,例如关闭浏览器窗口,那么在下次尝试运行该应用时,它很可能会卡住,无法继续执行。

问题根源分析

根据社区讨论,此问题主要与Streamlit和tqdm(以及stqdm作为其Streamlit封装)之间的锁定机制冲突有关。具体来说,当progress_apply操作在多线程或多进程环境下执行时,如果其内部的锁(lock)没有被正确释放或处理,并在意外中断后保持一个不一致的状态,那么在应用下次启动时,可能会因为尝试获取一个已被锁住但又无法释放的资源而导致死锁或冻结。这种现象在Windows操作系统上尤为常见。

解决方案:引入可重入锁

解决此问题的关键在于替换stqdm内部使用的默认锁机制,引入一个可重入锁(Reentrant Lock, RLock)。RLock允许同一个线程多次获取同一个锁,而不会导致死锁,只要每次获取都对应一次释放。这在某些复杂的并发场景中可以避免因自身尝试获取已持有的锁而导致的阻塞。虽然此问题的根本原因可能更为复杂,但使用RLock作为stqdm的锁机制,能够有效规避因中断导致的状态不一致问题。

Comet AI 浏览器
Comet AI 浏览器

下载 Comet AI 浏览器,体验由 Perplexity AI 驱动的革命性上网方式。内置 AI 助手可实时总结网页、跨标签页对比信息、自动执行任务。告别繁琐操作,让 AI 成为你的浏览副驾,大幅提升研究与工作效率。支持 Windows、macOS、Android 和 iOS。

下载

要应用此解决方案,只需在Streamlit脚本的开头,导入RLock并将其设置为stqdm的锁。

代码实践

以下是应用解决方案后的代码示例:

import streamlit as st
from time import sleep
import pandas as pd
import numpy as np
from stqdm import stqdm
from threading import RLock # 导入RLock

# 在脚本开头设置stqdm的锁为RLock
stqdm.set_lock(RLock())

def something_heavy(x):
    """模拟一个耗时操作"""
    sleep(1) # 暂停1秒
    return x * 100

# 创建一个示例DataFrame
df = pd.DataFrame(np.random.randint(0, 100, size=(10, 2)), columns=list('AB'))

# 注册stqdm到pandas,并显示进度条
stqdm.pandas(desc='正在执行繁重操作')
df['C'] = df.progress_apply(lambda row: something_heavy(row['A']), axis=1)
st.write(df)

通过在脚本顶部添加 from threading import RLock 和 stqdm.set_lock(RLock()) 这两行代码,即使在progress_apply执行过程中应用被中断,下次运行时也能正常启动,避免了冻结问题。

注意事项

  1. 放置位置: 务必将 stqdm.set_lock(RLock()) 放在Streamlit脚本的顶部,在任何可能调用 stqdm 或 stqdm.pandas 之前。这是为了确保在stqdm初始化其内部锁机制时,就使用我们指定的RLock。
  2. 平台差异: 尽管此问题在Windows系统上更为突出,但为了应用的健壮性,建议在所有部署环境中都采用此解决方案。
  3. 理解RLock: RLock是Python threading模块中的一个同步原语,它是一个可重入的互斥锁。这意味着同一个线程可以多次获取同一个RLock而不会死锁,但每次获取都必须有对应的释放操作。在这种特定情况下,它似乎能够更好地处理stqdm在Streamlit环境下的中断和恢复。

总结

stqdm库为Streamlit应用带来了极佳的用户体验,但在处理长时间运行的Pandas操作时,其与Streamlit的集成可能会在应用意外中断后导致冻结问题。通过在脚本开头简单地设置stqdm.set_lock(RLock()),我们可以有效地规避这一问题,确保Streamlit应用的稳定性和可靠性。这是一个简单而强大的修复,对于任何在Streamlit中使用stqdm.pandas的开发者来说都至关重要。

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

2025.12.04

149

15

Python 数据清洗与预处理实战
Python 数据清洗与预处理实战

本专题系统讲解 Python 在数据清洗与预处理中的核心技术,包括使用 Pandas 进行缺失值处理、异常值检测、数据格式化、特征工程与数据转换,结合 NumPy 高效处理大规模数据。通过实战案例,帮助学习者掌握 如何处理混乱、不完整数据,为后续数据分析与机器学习模型训练打下坚实基础。

2026.01.31

129

21

Python数据分析与Pandas高级实战
Python数据分析与Pandas高级实战

本专题围绕 Python 数据分析展开,系统讲解 Pandas 的高级用法,包括数据清洗、透视表、时间序列分析以及多表合并与分组操作。通过实战案例,帮助开发者掌握高效处理与分析数据的方法,提高数据处理效率与分析能力。

2026.04.13

69

25

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

2039

6

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

2025.12.24

618

20

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

2026.01.21

127

30

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

2026.01.21

315

24

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

2026.02.06

202

20

C++多线程并发控制与线程安全设计实践
C++多线程并发控制与线程安全设计实践

本专题围绕 C++ 在高性能系统开发中的并发控制技术展开,系统讲解多线程编程模型与线程安全设计方法。内容包括互斥锁、读写锁、条件变量、原子操作以及线程池实现机制,同时结合实际案例分析并发竞争、死锁避免与性能优化策略。通过实践讲解,帮助开发者掌握构建稳定高效并发系统的关键技术。

2026.03.16

93

22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PyCharm官方快速入门指南
PyCharm官方快速入门指南

共0课时 | 0人学习

Python函数定义官方教程
Python函数定义官方教程

共0课时 | 0人学习

Python 3.14.6官方文档
Python 3.14.6官方文档

共0课时 | 0人学习