[streamlit] 튜토리얼 > 여러 컨테이너에 걸쳐 fragment 생성
[출처] https://docs.streamlit.io/develop/tutorials/execution-flow/create-a-multiple-container-fragment
1. Intro
Streamlit을 사용하면 함수를 fragment로 전환하여 전체 스크립트와 독립적으로 재실행할 수 있습니다. fragment가 외부 컨테이너에 쓰지(write) 않는 경우, fragment를 다시 실행할 때마다 Streamlit은 모든 fragment 요소를 지우고 다시 그립니다. 그러나 fragment가 외부 컨테이너에 요소를 쓰는 경우에는 fragment를 재실행하는 동안 Streamlit이 해당 요소를 지우지 않습니다. 대신, 해당 요소는 다음 전체 스크립트가 재실행될 때까지 fragment가 재실행될 때마다 누적됩니다. fragment가 앱의 여러 컨테이너를 업데이트하도록 하려면 st.empty() 컨테이너를 사용하여 요소 누적을 방지하세요.
Applied concepts
- fragment를 사용하여 두 개의 독립적인 프로세스를 별도로 실행하세요.
- 다중 컨테이너에 걸쳐 fragment를 배포하세요.
Prerequisites
- 파이썬 환경에는 다음이 설치되어 있어야 합니다: streamlit>=1.37.0
- your-repository 는 깨끗한 작업 디렉터리가 있어야 합니다.
- fragment와 st.empty()에 대한 기본적인 이해가 있어야 합니다.
Summary
이 장난감 예제에서는 컨테이너 6개가 있는 앱을 빌드합니다. 3개의 컨테이너에는 주황색 고양이가 있습니다. 나머지 세 개의 컨테이너에는 검은 고양이가 있습니다. 사이드바에는 "검은 고양이 무리", "주황색 고양이 무리", "모든 고양이 무리" 등 세 개의 버튼이 있습니다. 고양이 무리는 느리기 때문에 fragment를 사용하여 Streamlit이 관련 프로세스를 효율적으로 실행할 수 있도록 도와줍니다. 검은 고양이와 주황색 고양이를 위한 두 개의 fragment를 만들 것입니다. 버튼은 사이드바에 있고 fragment는 본문의 컨테이너를 업데이트하므로 앱에 고양이가 너무 많지 않도록 (고양이가 너무 많을 수 있는 경우) st.empty()을 사용하는 트릭을 사용할 것입니다. 😻
구축할 내용을 살펴보세요:
import streamlit as st
import time
st.title("Cats!")
row1 = st.columns(3)
row2 = st.columns(3)
grid = [col.container(height=200) for col in row1 + row2]
safe_grid = [card.empty() for card in grid]
def black_cats():
time.sleep(1)
st.title("🐈⬛ 🐈⬛")
st.markdown("🐾 🐾 🐾 🐾")
def orange_cats():
time.sleep(1)
st.title("🐈 🐈")
st.markdown("🐾 🐾 🐾 🐾")
@st.fragment
def herd_black_cats(card_a, card_b, card_c):
st.button("Herd the black cats")
container_a = card_a.container()
container_b = card_b.container()
container_c = card_c.container()
with container_a:
black_cats()
with container_b:
black_cats()
with container_c:
black_cats()
@st.fragment
def herd_orange_cats(card_a, card_b, card_c):
st.button("Herd the orange cats")
container_a = card_a.container()
container_b = card_b.container()
container_c = card_c.container()
with container_a:
orange_cats()
with container_b:
orange_cats()
with container_c:
orange_cats()
with st.sidebar:
herd_black_cats(grid[0].empty(), grid[2].empty(), grid[4].empty())
herd_orange_cats(grid[1].empty(), grid[3].empty(), grid[5].empty())
st.button("Herd all the cats")
2. Build the example
2.1. Initialize your app
https://psystat.tistory.com/232
의 내용과 동일
2.2. Frame out your app's containers
1. 앱에 제목과 세 개의 컨테이너로 구성된 두 행을 추가합니다.
st.title("Cats!")
row1 = st.columns(3)
row2 = st.columns(3)
grid = [col.container(height=200) for col in row1 + row2]
파일을 저장하여 업데이트된 미리 보기를 확인하세요.
2. 검은 고양이 두 마리를 그리는 도우미 함수를 정의합니다.
def black_cats():
time.sleep(1)
st.title("🐈⬛ 🐈⬛")
st.markdown("🐾 🐾 🐾 🐾")
이 함수는 "고양이 두 마리의 무리"를 나타내며, time.sleep()을 사용하여 느린 프로세스를 시뮬레이션합니다. 나중에 그리드 카드 중 하나에 고양이 두 마리를 그릴 때 이 함수를 사용할 것입니다.
3. 다른 도우미 함수를 정의하여 두 마리의 주황색 고양이를 그립니다.
def orange_cats():
time.sleep(1)
st.title("🐈 🐈")
st.markdown("🐾 🐾 🐾 🐾")
4. (선택 사항) 그리드 카드 내에서 각 함수를 호출하여 함수를 테스트합니다.
with grid[0]:
black_cats()
with grid[1]:
orange_cats()
app.py 파일을 저장하여 미리 보기를 확인합니다. 완료되면 이 네 줄을 삭제합니다.
2.3. Define your fragments
각 fragment 사이드바와 세 개의 추가 컨테이너에 걸쳐 있으므로 사이드바를 사용하여 fragment의 본문을 담고 세 개의 컨테이너를 함수 인수로 전달할 수 있습니다.
1. st.fragment 데코레이터를 사용하여 검은 고양이 조각 정의를 시작하세요.
@st.fragment
def herd_black_cats(card_a, card_b, card_c):
2. 이 조각을 다시 실행하는 버튼을 추가합니다.
st.button("Herd the black cats")
3. 도우미 함수를 사용하여 각 컨테이너에 글을 씁니다.
with card_a:
black_cats()
with card_b:
black_cats()
with card_c:
black_cats()
위의 코드는 원하는 대로 동작하지 않지만 다음 단계에서 이 문제를 살펴보고 수정할 것입니다.
4. 코드를 테스트합니다. 사이드바에서 fragment 함수를 호출합니다.
with st.sidebar:
herd_black_cats(grid[0], grid[2], grid[4])
파일을 저장하고 사이드바의 버튼을 사용해 보세요. fragment를 다시 실행할 때마다 카드에 점점 더 많은 고양이가 나타납니다! 이것은 fragment가 외부 컨테이너에 쓸 때 예상되는 동작입니다. 이 문제를 해결하려면 fragment 함수에 st.empty() 컨테이너를 전달해야합니다.
5. 이전 두 단계의 코드 줄을 삭제합니다.
6. st.empty() 컨테이너를 사용할 준비를 하려면 다음과 같이 cat-herding 함수를 수정하세요. 버튼 뒤에 fragment에 전달할 st.empty() 카드에 넣을 컨테이너를 정의합니다.
container_a = card_a.container()
container_b = card_b.container()
container_c = card_c.container()
with container_a:
black_cats()
with container_b:
black_cats()
with container_c:
black_cats()
이 새 버전에서 card_a, card_b, card_c는 st.empty() 컨테이너가 됩니다. container_a, container_b, container_c를 생성하면 Streamlit이 각 그리드 카드에 여러 요소를 그릴 수 있습니다.
7. 마찬가지로 주황색 고양이 조각 함수를 정의합니다.
@st.fragment
def herd_orange_cats(card_a, card_b, card_c):
st.button("Herd the orange cats")
container_a = card_a.container()
container_b = card_b.container()
container_c = card_c.container()
with container_a:
orange_cats()
with container_b:
orange_cats()
with container_c:
orange_cats()
2.4. Put the functions together together to create an app
1. 사이드바에서 두 조각을 모두 호출합니다.
with st.sidebar:
herd_black_cats(grid[0].empty(), grid[2].empty(), grid[4].empty())
herd_orange_cats(grid[1].empty(), grid[3].empty(), grid[5].empty())
각 카드에 st.empty() 컨테이너를 생성하고 이를 fragment에 전달하면 fragment를 다시 실행할 때마다 카드에 요소가 쌓이는 것을 방지할 수 있습니다. 앱의 앞부분에 st.empty() 컨테이너를 생성하면 전체 스크립트 재실행 시 주황색 고양이 카드가 지워지고 검은색 고양이 카드가 먼저 렌더링됩니다.
2. fragment 외부에 버튼을 포함하세요. 버튼을 클릭하면 fragment 외부에서 위젯 함수를 호출하기 때문에 전체 스크립트 재실행이 트리거됩니다.
st.button("Herd all the cats")
3. 파일을 저장하고 앱을 사용해 보세요! "검은 고양이 무리" 또는 "주황색 고양이 무리"를 클릭하면 Streamlit은 관련 카드 세 장만 다시 그립니다. "모든 고양이 무리"를 클릭하면 스트림릿은 6장의 카드를 모두 다시 뽑습니다.