При использованииstreamlit я устанавливаю тяжелую функцию типа cache_data, чтобы избежать перерасчета. Поскольку эта функция требует много времени, я также хочу создать внутри нее индикатор выполнения. Однако я считаю, что он не может работать с указанным cache_data.
Ниже приводится MWE
import streamlit as st
from time import sleep
@st.cache_data(show_spinner = False)
def showProgressBar():
cur = 0
total = 100
my_bar = st.progress(cur / total, text = "%d / %d" % (cur, total))
while cur < total:
sleep(0.05)
cur = cur + 1
my_bar.progress(cur / total, text = "%d / %d" % (cur, total))
my_bar.empty()
### Main ###
st.set_page_config(page_title = "Test Progress In Cache Function", page_icon = ":bar_chart:",layout = "wide")
st.title(" :bar_chart: Test")
showProgressBar()
st.text('Test Finish')
Оказывается, панель с таким кодом никогда не появляется. Но если я закомментирую строку @st.cache_data, индикатор выполнения будет работать как положено.
В В этой теме аналогичная проблема упоминается о progress и st.cache, обходной путь, похоже, связан с suppress_st_warning = True, однако с обесцениванием st.cache этот параметр больше не доступен для st.cache_data
Кто-нибудь может здесь помочь?





Если для вас сложный расчет sleep(0.05), вот способ сделать это. Этот фрагмент кода извлекает тяжелые вычисления из обработки индикатора выполнения, гарантируя, что декоратор cache_data можно использовать только для операций, не связанных с Streamlit:
import streamlit as st
from time import sleep
from random import randint
@st.cache_data(show_spinner = False)
def do_heavy_calc(n):
print(f"First time seeing {n}")
sleep(0.05)
def showProgressBar():
cur = 0
total = 100
my_bar = st.progress(cur / total, text = "%d / %d" % (cur, total))
while cur < total:
n = randint(1, 100)
# Add a random number since I suppose you don't want to run
# the exact same function everytime(?)
do_heavy_calc(n)
cur = cur + 1
my_bar.progress(cur / total, text = "%d / %d" % (cur, total))
my_bar.empty()
### Main ###
st.set_page_config(page_title = "Test Progress In Cache Function", page_icon = ":bar_chart:",layout = "wide")
st.title(" :bar_chart: Test")
showProgressBar()
st.text('Test Finish')
Однако если вы хотите отслеживать одну длинную функцию, которую вы вызываете только один раз, вы можете преобразовать ее в генератор, который возвращает текущий шаг, на котором в данный момент находится функция do_heavy_calc. Однако я не рекомендую это делать (это кажется немного хакерским), но в моих тестах это работает нормально.
Две вещи, на которые следует обратить внимание:
cache_data заменяется на cache_resource, поскольку cache_data повышает streamlit.runtime.caching.cache_errors.UnserializableReturnValueError._) перед двумя входными аргументами: это необходимо для того, чтобы гарантировать, что они не будут использоваться в целях кэширования. См. эту страницу документации с потоковой подсветкой в разделе «Исключение входных параметров».import streamlit as st
from time import sleep
@st.cache_resource(show_spinner = False)
def do_heavy_calc(_cur, _total):
while _cur < _total:
# yield where you are so that the progress bar on the outside can
# keep track
yield _cur
sleep(0.05)
_cur = _cur + 1
def showProgressBar():
min_ = 0
max_ = 100
my_bar = st.progress(min_ / max_, text = "%d / %d" % (min_, max_))
for c in do_heavy_calc(0, max_):
my_bar.progress(c / max_, text = "%d / %d" % (c, max_))
my_bar.empty()
### Main ###
st.set_page_config(page_title = "Test Progress In Cache Function", page_icon = ":bar_chart:",layout = "wide")
st.title(" :bar_chart: Test")
showProgressBar()
st.text('Test Finish')
Спасибо @vvvvv. Мне помогает первый способ. Второе кажется немного сложным. Кажется, они оба помещают
st.progressснаружиst.cache_dataилиst.cache_resource, поэтому, когда цикл с потоковым освещением запускается снова, полоса всегда будет отображаться, но прогрессировать быстро, этого достаточно для моего случая.