前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python应用开发——30天学习Streamlit Python包进行APP的构建(4)

Python应用开发——30天学习Streamlit Python包进行APP的构建(4)

作者头像
此星光明
发布2024-05-31 12:55:14
1520
发布2024-05-31 12:55:14
举报

通过构建 Bored API 应用学习如何使用 API

Bored API 应用可以在你无聊的时候建议你做些有意思的事!

技术上来说,这也演示了如何在 Streamlit 应用内使用 API。

示例应用

代码

以下是如何实现上述 Bored API 应用:

代码语言:javascript
复制
import streamlit as st
import requests

#设置一个标题
st.title('🏀 Bored API app')

#设置一个侧边栏的抬头
st.sidebar.header('Input')
#添加一个选择框
selected_type = st.sidebar.selectbox('Select an activity type', ["education", "recreational", "social", "diy", "charity", "cooking", "relaxation", "music", "busywork"])

#获取制定链接数据
suggested_activity_url = f'http://www.boredapi.com/api/activity?type={selected_type}'
json_data = requests.get(suggested_activity_url)
suggested_activity = json_data.json()

#设定两列
c1, c2 = st.columns(2)
#第一个是扩展器
with c1:
  with st.expander('About this app'):
    st.write('Are you bored? The **Bored API app** provides suggestions on activities that you can do when you are bored. This app is powered by the Bored API.')
#设定第二个扩展器
with c2:
  with st.expander('JSON data'):
    st.write(suggested_activity)

#设定主面板的标题
st.header('Suggested activity')
st.info(suggested_activity['activity'])

#主面板设定三列
col1, col2, col3 = st.columns(3)
with col1:
  st.metric(label='Number of Participants', value=suggested_activity['participants'], delta='')
with col2:
  st.metric(label='Type of Activity', value=suggested_activity['type'].capitalize(), delta='')
with col3:
  st.metric(label='Price', value=suggested_activity['price'], delta='')

逐行解释

创建 Streamlit 应用时要做的第一件事就是将 streamlit 库导入为 st,并且导入要用到的 requests 库:

代码语言:javascript
复制
import streamlit as st 
import requests

然后用 st.title 显示应用的标题:

代码语言:javascript
复制
st.title('🏀 Bored API app')

接下来我们将通过 st.selectbox 命令接收用户输入的活动类型

代码语言:javascript
复制
st.sidebar.header('Input')
selected_type = st.sidebar.selectbox('Select an activity type', ["education", "recreational", "social", "diy", "charity", "cooking", "relaxation", "music", "busywork"])

上述选择的活动类型会通过 f-字符串追加到请求链接之后,然后被用于请求 JSON 数据:

代码语言:javascript
复制
suggested_activity_url = f'http://www.boredapi.com/api/activity?type={selected_type}'
json_data = requests.get(suggested_activity_url)
suggested_activity = json_data.json()

以下我们将通过 st.expander 命令显示应用的说明以及获取到的 JSON 数据:

代码语言:javascript
复制
c1, c2 = st.columns(2)
with c1:
  with st.expander('About this app'):
    st.write('Are you bored? The **Bored API app** provides suggestions on activities that you can do. This app is powered by the Bored API.')
with c2:
  with st.expander('JSON data'):
    st.write(suggested_activity)

然后我们会像下面这样将建议的活动显示出来

代码语言:javascript
复制
st.header('Suggested activity')
st.info(suggested_activity['activity'])

最后,我们也会显示所建议活动随附的信息,比如参与人数、活动类型与价格。

代码语言:javascript
复制
col1, col2, col3 = st.columns(3)
with col1:
  st.metric(label='Number of Participants', value=suggested_activity['participants'], delta='')
with col2:
  st.metric(label='Type of Activity', value=suggested_activity['type'].capitalize(), delta='')
with col3:
  st.metric(label='Price', value=suggested_activity['price'], delta='')

延伸阅读

st.info

这里面的第二个参数是一个icon,也就是一个符号

在警报旁边显示的可选表情符号或图标。如果图标为 "无"(默认),则不显示图标。如果图标是字符串,则以下选项有效:

单字符表情符号。例如,可以设置 icon="🚨" 或 icon="🔥"。不支持表情符号简码。

材料符号库(轮廓样式)中的图标,格式为":material/icon_name:",其中 "icon_name "是蛇形图标的名称。

例如,icon=":material/thumb_up: "将显示拇指向上图标。在 Material Symbols 字体库中查找其他图标。

代码语言:javascript
复制
import streamlit as st

st.info('This is a purely informational message', icon="ℹ️")

🗓️ 天 27

使用 Streamlit Elements 搭建一个可拖拽放缩的仪表盘

Streamlit Elements 是一个由 okld 制作的第三方组件,能够让你用 Material UI 组件、Monaco 编辑器(Visual Studio Code)和 Nivo charts 等等搭建出精美的应用和仪表盘。

如何使用?

安装

第一步要做的就是将 Streamlit Elements 安装到你的环境中:

代码语言:javascript
复制
pip install streamlit-elements==0.1.*

我们推荐你将其版本固定到 0.1.*,因为此后的版本中可能引入变动破坏 API 向后兼容性。

用法

你可以参考 Streamlit Elements README 中给出的深度用法指南。

我们要做什么?

今天挑战的目标是做一个包含三个 Material UI 卡片的仪表盘:

  • 第一个卡片包含 Monaco 编辑器用于输入数据
  • 第二个卡片用 Nivo Bump 图显示输入的数据
  • 第三个卡片用来显示 st.text_input 指定连接的 YouTube 视频

你可以使用 Nivo Bump 示例中“data”标签页下生成的数据:Bump chart | nivo.

示例应用

代码 逐行解释

代码语言:javascript
复制
# 首先,我们需要给应用导入以下的库

import json
import streamlit as st
from pathlib import Path

# 然后我们需要 Streamlit Elements 中的这些对象
# 有关全部对象及其用法的说明请见:https://github.com/okld/streamlit-elements#getting-started

from streamlit_elements import elements, dashboard, mui, editor, media, lazy, sync, nivo

# 更改页面布局,让仪表盘占据整个页宽

st.set_page_config(layout="wide")

with st.sidebar:
    st.title("🗓️ #30DaysOfStreamlit")
    st.header("Day 27 - Streamlit Elements")
    st.write("Build a draggable and resizable dashboard with Streamlit Elements.")
    st.write("---")

    # 媒体播放器所用的 URL
    media_url = st.text_input("Media URL", value="https://www.youtube.com/watch?v=vIQQR_yq-8I")

# 初始化代码编辑器和图表的默认数据
#
# 在这篇教程中,我们会用到 Nivo Bump 图的数据
# 你能在“data”标签页下获取随机的数据:https://nivo.rocks/bump/
#
# 如下所示,当代码编辑器发生更改时,会话状态就会被更新
# 然后会被读入至 Nivo Bump 图并将其绘制出来

if "data" not in st.session_state:
    st.session_state.data = Path("data.json").read_text()

# 定义默认的仪表盘布局
# 默认情况下仪表盘会分为 12 列
#
# 更多可用参数见:
# https://github.com/react-grid-layout/react-grid-layout#grid-item-props

layout = [
    # 编辑器对象定位在坐标 x=0 且 y=0 处,占据 12 列中的 6 列以及 3 行
    dashboard.Item("editor", 0, 0, 6, 3),
    # 图表对象定位在坐标 x=6 且 y=0 处,占据 12 列中的 6 列以及 3 行
    dashboard.Item("chart", 6, 0, 6, 3),
    # 媒体播放器对象定位在坐标 x=0 且 y=3 处,占据 12 列中的 6 列以及 4 行
    dashboard.Item("media", 0, 3, 12, 4),
]

# 创建显示各元素的框体

with elements("demo"):

    # 使用以上指定的布局创建新仪表盘
    #
    # draggableHandle 是一个 CSS 查询选择器,定义了仪表盘中可拖拽的部分
    # 以下为将带 'draggable' 类名的元素变为可拖拽对象
    #
    # 更多仪表盘网格相关的可用参数请见:
    # https://github.com/react-grid-layout/react-grid-layout#grid-layout-props
    # https://github.com/react-grid-layout/react-grid-layout#responsive-grid-layout-props

    with dashboard.Grid(layout, draggableHandle=".draggable"):

        # 第一个卡片,代码编辑器
        #
        # 我们使用 'key' 参数来选择正确的仪表盘对象
        #
        # 为了让卡片的内容自动填充占满全部高度,我们将使用 flexbox CSS 样式
        # sx 是所有 Material UI 组件均可使用的参数,用于定义其 CSS 属性
        #
        # 有关卡片、flexbox 和 sx 的更多信息,请见:
        # https://mui.com/components/cards/
        # https://mui.com/system/flexbox/
        # https://mui.com/system/the-sx-prop/

        with mui.Card(key="editor", sx={"display": "flex", "flexDirection": "column"}):

            # 为了让标题可拖拽,我们只需要将其类名设为 'draggable'
            # 与 dashboard.Grid 当中 draggableHandle 的查询选择对应

            mui.CardHeader(title="Editor", className="draggable")

            # 要使卡片内容占满全高,我们需要将 CSS 样式中 flex 的值设为 1
            # 同时我们也想要卡片内容随卡片缩放,因此将其 minHeight 设为 0

            with mui.CardContent(sx={"flex": 1, "minHeight": 0}):

                # 以下是我们的 Monaco 代码编辑器
                #
                # 首先,我们将其默认值设为之前初始化好的 st.session_state.data
                # 其次,我们将设定所用的语言,这里我们设为 JSON
                #
                # 接下来,我们想要获取编辑器中内容的变动
                # 查阅 Monaco 文档后,我们发现可以用 onChange 属性指定一个函数
                # 这个函数会在每次变动发生后被调用,并且变更后的内容将被传入函数
                # (参考 onChange: https://github.com/suren-atoyan/monaco-react#props)
                #
                # Streamlit Elements 提供了一个特殊的 sync() 函数
                # 能够创建一个自动将其参数同步到 Streamlit 会话状态的回调函数
                #
                # 样例
                # --------
                # 创建一个自动将第一个参数同步至会话状态中 "data" 的回调函数:
                # >>> editor.Monaco(onChange=sync("data"))
                # >>> print(st.session_state.data)
                #
                # 创建一个自动将第二个参数同步至会话状态中 "ev" 的回调函数:
                # >>> editor.Monaco(onChange=sync(None, "ev"))
                # >>> print(st.session_state.ev)
                #
                # 创建一个自动将两个参数同步至会话状态的回调函数:
                # >>> editor.Monaco(onChange=sync("data", "ev"))
                # >>> print(st.session_state.data)
                # >>> print(st.session_state.ev)
                #
                # 那么问题来了:onChange 会在每次发生变动时被调用
                # 那么意味着每当你输入一个字符,整个 Streamlit 应用都会重新运行
                #
                # 为了避免这个问题,可以使用 lazy() 令 Streamlit Elements 等待其他事件发生
                # (比如点击按钮)然后再将更新后的数据传给回调函数
                #
                # 有关 Monaco 其他可用参数的说明,请见:
                # https://github.com/suren-atoyan/monaco-react
                # https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html

                editor.Monaco(
                    defaultValue=st.session_state.data,
                    language="json",
                    onChange=lazy(sync("data"))
                )

            with mui.CardActions:

                # Monaco 编辑器已经将一个延迟回调函数绑定至 onChange 了,因此即便你更改了 Monaco 的内容
                # Streamlit 也不会立刻接收到,因此不会每次都重新运行
                # 因此我们需要另一个非延迟的事件来触发更新
                #
                # 解决方法就是创建一个在点击时回调的按钮
                # 我们的回调函数实际上不需要做任何事
                # 你可以创建一个空的函数,或者直接使用不带参数的 sync()
                #
                # 然后每当你点击按钮的时候,onClick 回调函数会被调用
                # 而期间其他延迟调用了的回调函数也会被一并执行

                mui.Button("Apply changes", onClick=sync())

        # 第二个卡片,Nivo Bump 图
        # 我们将使用和第一个卡片同样的 flexbox 配置来自动调整内容高度

        with mui.Card(key="chart", sx={"display": "flex", "flexDirection": "column"}):

            # 为了让标题可拖拽,我们只需要将其类名设为 'draggable'
            # 与 dashboard.Grid 当中 draggableHandle 的查询选择对应

            mui.CardHeader(title="Chart", className="draggable")

            # 和前面一样,我们想要让我们的内容随着用户缩放卡片而缩放
            # 因此将 flex 属性设为 1,minHeight 设为 0

            with mui.CardContent(sx={"flex": 1, "minHeight": 0}):

                # 以下我们将绘制 Bump 图
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 示例应用
  • 代码
  • 逐行解释
  • 延伸阅读
  • st.info
  • 🗓️ 天 27
  • 使用 Streamlit Elements 搭建一个可拖拽放缩的仪表盘
    • 安装
      • 用法
        • 我们要做什么?
          • 示例应用
            • 代码 逐行解释
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档