Create a fragment across multiple containers

Streamlit 允许你将函数转换为片段,这些片段可以独立于完整脚本重新运行。如果你的片段没有写入外部容器,Streamlit 将在每次片段重新运行时清除并重新绘制所有片段元素。然而,如果你的片段确实将元素写入外部容器,Streamlit 在片段重新运行时不会清除这些元素。相反,这些元素会在每次片段重新运行时累积,直到下一次完整脚本重新运行。如果你希望片段更新应用程序中的多个容器,请使用st.empty()容器以防止元素累积。

  • 使用片段分别运行两个独立的进程。
  • 将片段分发到多个容器中。
  • 您的Python环境中必须安装以下内容:

    streamlit>=1.37.0
  • 你应该有一个干净的工作目录,名为 your-repository

  • 你应该对片段和st.empty()有一个基本的理解。

在这个简单的示例中,你将构建一个包含六个容器的应用程序。三个容器将有橙色猫,另外三个容器将有黑色猫。你将在侧边栏中放置三个按钮:“聚集黑色猫”、“聚集橙色猫”和“聚集所有猫”。由于聚集猫的过程较慢,你将使用片段来帮助Streamlit高效地运行相关进程。你将创建两个片段,一个用于黑色猫,另一个用于橙色猫。由于按钮将位于侧边栏,而片段将更新主体中的容器,你将使用st.empty()的技巧来确保你的应用程序中不会出现太多猫(如果真的有太多猫的话)。😻

以下是您将要构建的内容:

Complete codeexpand_more
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")
  1. your_repository 中,创建一个名为 app.py 的文件。

  2. 在终端中,将目录更改为 your_repository 并启动您的应用程序。

    streamlit run app.py

    由于您仍然需要添加代码,您的应用程序将是空白的。

  3. app.py 中,编写以下内容:

    import streamlit as st import time

    你将使用 time.sleep() 来减慢速度并观察片段的工作情况。

  4. 保存您的app.py文件并查看正在运行的应用程序。

  5. 点击“始终重新运行”或在运行的应用中按下“A”键。

    当您保存对app.py的更改时,您的运行预览将自动更新。您的预览仍然会是空白的。返回您的代码。

  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文件以查看预览。完成后删除这四行。

由于每个片段将跨越侧边栏和三个额外的容器,您将使用侧边栏来保存片段的主体,并将这三个容器作为函数参数传递。

  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. 测试你的代码。在侧边栏中调用你的片段函数。

    with st.sidebar: herd_black_cats(grid[0], grid[2], grid[4])

    保存你的文件并尝试使用侧边栏中的按钮。每次片段重新运行时,卡片中会出现越来越多的猫!这是片段写入外部容器时的预期行为。要解决这个问题,你将传递st.empty()容器给你的片段函数。

    Example Streamlit app showing accumulating elements when a fragment writes to outside containers
  5. 删除前两个步骤中的代码行。

  6. 为了准备使用st.empty()容器,请按以下方式修正你的猫群管理函数。在按钮之后,定义容器以放置在你将传递给片段的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_acard_bcard_c将是st.empty()容器。你创建了container_acontainer_bcontainer_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()
  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()容器并将它们传递给你的片段,你可以防止元素在每次片段重新运行时在卡片中累积。如果你在应用程序的早期创建st.empty()容器,全脚本重新运行将清除橙色猫卡片,同时(首次)渲染黑色猫卡片。

  2. 在你的片段之外包含一个按钮。当点击时,按钮将触发整个脚本的重新运行,因为你在任何片段之外调用了它的widget函数。

    st.button("Herd all the cats")
  3. 保存您的文件并尝试使用应用程序!当您点击“聚集黑猫”或“聚集橘猫”时,Streamlit 只会重新绘制相关的三张卡片。当您点击“聚集所有猫”时,Streamlit 会重新绘制所有六张卡片。

forum

还有问题吗?

我们的 论坛 充满了有用的信息和Streamlit专家。