Streamlit简介

Streamlit是一个基于Python的可视化工具,和其他可视化工具不同的是,它生成的是一个可交互的站点(页面)。但同时它又不是我们常接触的类似Django、Flask这样的WEB框架。当前使用下来的感受:

缺点:

  • 自带服务器,且需要从命令行启动服务方能查看页面,不能通过直接运行Python代码的方式启动应用。即不能集成到其他系统及框架中
  • 当前只支持单页面,不能通过URL传参等方式生成多页面。Github有人提了Issues,但是目前还没支持,部分人给了一些临时的Hack
  • 目前不支持登录验证,且由于自带服务器的原因,很难集成其他第三方的登录验证等,不能做很好的数据权限控制

优点:

  • 无需编写任何HTML、CSS或JS代码就可以生成界面不错的页面

整体评价:优势明显,定位于只熟悉Python代码的算法人员。虽然目前的功能比较简陋,问题较多,但随着不断的开发,相信功能也会也来越强大。

Streamlit带来的改变

原先的数据展示页面开发流程:

  1. 在Jupyter中开发演示
  2. 将Python代码复制到文件
  3. 编写Flask应用,包括考虑HTTP请求、HTML代码、JS和回调等

而当展示页面非常重要时,通常的流程是这样的:

  1. 收集用户需求
  2. 定义展示框架与原型
  3. 使用HTML、CSS、Python、React、Javascript等进行编码
  4. 一个月以后才能看到最终的页面

Streamlit的流程:

  • 稍微改下Python代码即可生成展示界面

而能够快速生成应用,主要原因是Streamlit兼容以下Python库或框架:

  • 数据处理:Numpy、Pandas
  • 机器学习框架或库:Scilit-Learn、TensorFlow、Keras、PyTorch
  • 数据可视化工具:matplotlib、seaborn、poltly、boken、Altair、GL、Vega-Lite
  • 文本处理:Markdown、LaTeX

Streamlit使用指南

上面介绍的感觉有些摸不着头脑,接下来直接用代码来演示。

常用命令

# 启动运行APP
streamlit run your_script.py
 
# 显示配置文档
streamlit config show
 
# 清除缓存
streamlit cache clear

显示文本

import streamlit as st
 
st.title("标题")
st.header("My Website")
st.subheader("Data Analytics")
st.text("Simple text")
st.write("Hello World!")
st.markdown('Streamlit is **_really_ cool**.')
st.latex('E=MC^2')
st.success('Success!')
st.warning('Warning!')
st.error('Error!')
st.code("""
class MyClass:
def __init__(self):
super(MyClass, self).__init__()
""")
 
st.json({
"pagination": {
"total": 100,
"per_page": 20,
"page": 1,
},
"items": [
{
"id": 1,
"name": "admin",
"email": "admin@test.com",
"is_superuser": True
}
]
})

展现内容如下:

从上面可以看到,Streamlit可以非常方便的相似不同层级的title(目前只支持3种,类似H1~H3),同时支持文本、LaTeX、Markdown、Code和JSON、Emoji的输出。也支持信息的反馈的支持(成功、警告、错误)。

另外st.write()支持各种类型的数据:

  • write(string):显示字符串或Markdown 字符串,同时支持LaTeX、emoji shortcodes
  • write(data_frame) : 显示DataFrame表格
  • write(error) : 显示错误信息
  • write(func) : 显示function信息
  • write(module) : 显示module的信息
  • write(dict) : Displays dict in an interactive widget.
  • write(obj) : 打印字符串对象
  • write(mpl_fig) : 显示Matplotlib图片
  • write(altair) : 显示Altair图表
  • write(keras) : 显示Keras模型
  • write(graphviz) : 显示Graphviz图片
  • write(plotly_fig) : 显示Plotly图片
  • write(bokeh_fig) : 显示Bokeh图片
  • write(sympy_expr) : 使用LaTeX 显示SymPy语法

显示数据

import streamlit as st
import pandas as pd
import numpy as np
 
df = pd.DataFrame(np.random.randn(10, 20), columns=('col %d' % i for i in range(20)))
st.dataframe(df)
st.table(df)

显示内容:

可以看到,使用st.dataframe(df)相比st.table(df)界面要好看些。

显示图表

import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
 
df = pd.DataFrame(np.random.randn(20, 3), columns=['a', 'b', 'c'])
st.line_chart(df)
st.area_chart(df)
st.bar_chart(df)
 
arr = np.random.normal(1, 1, size=100)
plt.hist(arr, bins=20)
st.pyplot()
 
df_location = pd.DataFrame(np.random.randn(1000, 2) / [50, 50] + [37.76, -122.4], columns=['lat', 'lon'])
st.map(df_location)
 
# st.altair_chart()
# st.vega_lite_chart()
# st.plotly_chart()
# st.bokeh_chart()
# st.pydeck_chart()
# st.deck_gl_chart()
# st.graphviz_chart()

可以看到这里支持目前市面上的各种图表的Python库。

显示媒体

这里的媒体包括:图片、音频、视频。

import streamlit as st
 
st.image()
st.audio()
st.video()

这里不详细介绍,具体可以见官方文档

交互组件

import streamlit as st
import pandas as pd
 
# 按钮
if st.button('Say hello'):
st.write('Why hello there')
else:
st.write('Goodbye')
 
# 勾选项
agree = st.checkbox('I agree')
if agree:
st.write('Great!')
 
# 单选项
genre = st.radio("What's your favorite movie genre", ('Comedy', 'Drama', 'Documentary'))
if genre == 'Comedy':
st.write('You selected comedy.')
else:
st.write("You didn't select comedy.")
 
# 下拉框
option = st.selectbox('How would you like to be contacted?', ('Email', 'Home phone', 'Mobile phone'))
st.write('You selected:', option)
 
# 多选框
options = st.multiselect('What are your favorite colors', ['Green', 'Yellow', 'Red', 'Blue'], ['Yellow', 'Red'])
st.write('You selected:', options)
 
# 滑块(单)
age = st.slider('How old are you?', 0, 130, 25)
st.write("I'm ", age, 'years old')
 
# 滑块(双)
values = st.slider('Select a range of values', 0.0, 100.0, (25.0, 75.0))
st.write('Values:', values)
 
# 输入框
title = st.text_input('Movie title', 'Life of Brian')
st.write('The current movie title is', title)
 
# 数字选择项
number = st.number_input('Insert a number')
st.write('The current number is ', number)
 
# 多行输入框
txt = st.text_area('Text to analyze', '''
It was the best of times, it was the worst of times, it was
the age of wisdom, it was the age of foolishness, it was
the epoch of belief, it was the epoch of incredulity, it
was the season of Light, it was the season of Darkness, it
was the spring of hope, it was the winter of despair, (...)
''')
 
# 上传文件
uploaded_file = st.file_uploader("Choose a CSV file", type="csv")
if uploaded_file is not None:
data = pd.read_csv(uploaded_file)
st.write(data)
 
# 颜色选择
color = st.beta_color_picker('Pick A Color', '#00f900')
st.write('The current color is', color)

侧边栏

import streamlit as st
 
option = st.sidebar.write("Hello World!")

缓存机制

Streamlit遵循由上至下的运行顺序,所以每次代码中有进行任何更改,都会重新开始运行一遍,会十分耗时。@st.cache会对封装起来的函数进行缓存,避免二次加载。如果函数中的代码发生变动,cache会重新加载一遍并缓存起来。假如将代码还原到上一次版本,由于先前的数据已经缓存起来了,所以不会进行二次加载。

@st.cache # This function will be cached
def my_slow_function(arg1, arg2):
# Do something really slow in here!
return the_output

当使用@st.cache 装饰器标记一个函数时,这将告诉steamlit在此函数被调用的时候应当检查以下事情:

  • 缓存函数的输入参数
  • 缓存函数使用的外部变量的值
  • 缓存函数主体
  • 缓存函数中调用到的函数的主题

若streamlit是初次看到这四个部分的确切值,组合方法和顺序,那么streamlit将执行这个函数并将结果保存在本地缓存中。下次当缓存函数被调用的时候,若这些部分没有变化,streamlit将直接返回之前缓存中的结果作为输出。

举个例子,当函数 expensive_computation(a, b), 被 @st.cache装饰时,并以 a=2 和 b=21执行, Streamlit会进行以下操作:

  • 计算缓存的key
  • 若key可以在缓存中找到,则:
    • 提取出以前的缓存元组(缓存输出和缓存输出的hash)
    • 执行输出突变检查, 计算输出的新哈希并将其与存储的output_hash进行比较。
      • 若两hash不同,显示告警Cached Object Mutated。(Note: 设置allow_output_mutation=True 可以禁用这步)。
    • 若输入的hash在缓存中找不到:
      • 执行缓存函数 (i.e. output = expensive_computation(2, 21))
      • 根据函数的output计算output_hash
      • 将key → (output, output_hash)存入缓存
    • 返回输出

如果遇到错误,则会引发异常。.如果在对键或输出进行哈希处理时发生错误,则会引发UnhashableTypeError 错误。

如上所述,Streamlit的缓存功能依赖于散列来计算缓存对象的键,并检测缓存结果中的意外变化。为了增强表达能力,Streamlit允许您使用hash_funcs参数覆盖此哈希过程。比如函数打开一个文件,默认情况下,它的hash是属性filename的hash。只要文件名不变,哈希值将保持不变。可以使用@st.cache装饰器的 hash_funcs 参数:

import io
 
def hash_io(input_io):
return (input_io.getvalue(), input_io.tell())
 
 
@st.cache(hash_funcs={io.BytesIO: hash_io, io.StringIO: hash_io})
def load_data(file_data):
try:
return pd.read_csv(file_data)
except:
return pd.read_excel(file_data)

Streamlit使用Hack

掩藏底部链接

hide_st_style = "<style># MainMenu {visibility: hidden;} footer {visibility: hidden;}</style>"
st.markdown(hide_st_style, unsafe_allow_html=True)

支持使用folium展示地图

st.markdown(map._repr_html_(), unsafe_allow_html=True)

如下报错:(地图不能显示)

Make this Notebook Trusted to load map: File -> Trust Notebook

解决方案:pip install branca==3.1.0

支持通过URL获取参数

备注:仅在0.58.0版本测试通过,新版本应该已经支持获取URL参数了。

1、找到tornado的安装路径

import tornado
print(tornado.__file__)

2、修改tornado下的routing.py文件

class _RoutingDelegate(httputil.HTTPMessageDelegate):
def __init__(self, router, server_conn, request_conn):
self.server_conn = server_conn
self.request_conn = request_conn
self.delegate = None
self.router = router # type: Router
 
def headers_received(self, start_line, headers):
request = httputil.HTTPServerRequest(
connection=self.request_conn,
server_connection=self.server_conn,
start_line=start_line, headers=headers)
 
# 添加代码
if request.query != '':
self.request_conn.params.urlpara = dict()
psl = request.query.split('&')
for ps in psl:
pl = ps.split('=')
self.request_conn.params.urlpara[pl[0]]=pl[1]
## 添加代码终止
 
self.delegate = self.router.find_handler(request)
if self.delegate is None:
app_log.debug("Delegate for %s %s request not found",
start_line.method, start_line.path)
self.delegate = _DefaultMessageDelegate(self.request_conn)
 
return self.delegate.headers_received(start_line, headers)

3、重启应用后进行测试:https://127.0.0.1:8501/?mypara1=99

import streamlit as st
from streamlit.server.Server import Server
 
sessions = Server.get_current()._session_info_by_id
session_id_key = list(sessions.keys())[0]
session = sessions[session_id_key]
urlPara = session.ws.request.connection.params.urlpara
 
st.write("URL PARAM:"+str(urlPara))支持

DataFrame支持样式定义问题

df.style.format({'col1': '{:.0f}', 'col2': '{:,.2%}'})

通过以上方法可以控制dataframe中字段的显示精度问题或按百分比显示等,但往往会报错,原因是pandas 1.1.0升级后导致的。

解决方案是退回老版本:pip install pandas==1.0.0

支持不同URL类型的不同页面共存

上面URL获取参数存在一定的Bug,即当访问一个带参数的URL过后,再刷新其他的页面,以前带的参数会还保存下来,解决方式是部署不同页面,不同页面使用不同的端口。然后再通过Nginx进行URL映射:

server{
listen 80;
server_name streamlit.domain.com;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
 
# streamlit specific:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
 
location /app1/ {
proxy_pass http://172.17.0.2:8501/;
}
location /app2/ {
proxy_pass http://172.17.0.2:8502/;
}
location / {
proxy_pass http://172.17.0.2:8503/;
}
}

支持账号密码登录

Stremlit本身不带登录验证,对于一些数据型的应用可能需要权限才能查看,一种简单的方法是每个应用最外层加上输入框,在用户输入的字符不等于代码中支付时,不显示内容。另外一种方案是,可以使用nginx的auth:

location / {
auth_basic "登录认证";
auth_basic_user_file /etc/nginx/conf/pass_file;
autoindex on;
proxy_pass http://172.17.0.2:8501/;
}

Streamlit的替代品

Streamlit最大的竞争敌手主要是Plotly Dash,相对Streamlit目前的功能更加完善,但是学习曲线相比Streamlit会稍微高一些。但从整体上对Streamlit的前景会更看好些。主要是Plotly Dash把其主要限制在了Plot.ly。两者在Github上的表现如下:

关于Plotly Dash的更多资料,期待下次有时间可以做更多的系统化整理。

参考资料:

Streamlit:快速数据可视化界面工具的更多相关文章

  1. 开源 Web 相册程序: Photoview 和数据可视化生成工具:Datawrapper

    Photoview Photoview是一个开源 Web 相册程序,Go 语言写的,使用 Docker 安装,可以用来快速架设个人相册. github地址:https://github.com/pho ...

  2. 大数据可视化呈现工具LightningChart的用法

    LightningChart (LightningChart Ultimate) 软件开发工具包是微软VisualStudio 的一个插件,专攻大数据可视化呈现问题,用于WPF(WindowsPres ...

  3. 开源数据可视化BI工具SuperSet(使用)

    上一篇介绍了Linux 下如何安装SuperSet ,本篇简单介绍一下如何使用 1.输入安装时设置的用户名密码登录控制台  2.控制界面如下  3.第一步添加数据源(已安装好的mysql) 点击 da ...

  4. Docker容器和数据可视化管理工具Flocker

    Flocker 可轻松实现 Docker 容器及其数据的管理.这是一个数据卷管理器和多主机的 Docker 集群管理工具,你可以通过它来控制数据.可用来在 Docker 中运行你的数据库.查询和 K/ ...

  5. Redis 可视化界面工具:Fastoredis

    下载地址:https://sourceforge.net/projects/fastoredis/

  6. 数据可视化界面UI设计大屏展示

  7. 开源数据可视化BI工具SuperSet(安装)

    本次安装教程共分两大步骤,因为Superset 基于python3编写的web应用(flask) 所以要求python3环境,故首先要将linux系统自带的环境进行升级,已经是python3的可跳过- ...

  8. BI数据可视化工具怎么选?用这款就够了!

    任何一项产品的选择都需要谨慎而全面,BI数据可视化工具的选择就更不用说了.作为企业的IT部门,如果没有良好的BI工具支持,IT部门将会十分容易陷入困境.那么面对多元化的BI工具市场,IT部门该如何选择 ...

  9. 超级干货 :一文读懂数据可视化 ZT

    前言 数据可视化,是指将相对晦涩的的数据通过可视的.交互的方式进行展示,从而形象.直观地表达数据蕴含的信息和规律. 早期的数据可视化作为咨询机构.金融企业的专业工具,其应用领域较为单一,应用形态较为保 ...

随机推荐

  1. window 消息传递机制【复杂版本】

    一.消息概述     众人周知,window系统是一个消息驱动的系统, windows操作系统本身有自己的消息队列称做系统消息队列(操作系统队列),消息循环,它捕捉键盘,鼠标的动作生成消息,并将这个消 ...

  2. Win11右键菜单怎么修改为传统Win10右键风格?

    前言 对于开发者而言,右键菜单会集成一些功能,升级 Win11 的右键菜单反而对开发造成不便,所以修改回传统风格. 修改成果如下 两个步骤改回传统右键风格 第一步:首先用鼠标右键点击开始菜单,选择 w ...

  3. 通过对比语法差异,让会JAVA的你快速学会Kotlin的开源宝藏项目

    今天有个小伙伴来问TJ君,说自己JAVA用的贼溜,想再学习下Kotlin,问TJ君上手难不难? 怎么说呢?其实TJ君一直觉得语言这方面,是触类旁通.一通百通的,既然JAVA已经贼溜了,想必学其他的语言 ...

  4. Pycharm:一直connecting to console的解决办法

    方法一: 1.打开Anaconda cmd(也就是Anaconda Prompt,在启动栏Anaconda目录里应该有)2.输入echo %PATH% 获得PATH value3.在PyCharm中, ...

  5. Java:代码改进技巧

    1.类名首字母大写:方法名首字母小写:常量名全大写: 2.当控制语句只有一句时,可以省略大括号{}:但是,建议任何时候都保留大括号,因为这是Java语句块的标志 3.用某个接口承接实现类时(多态),之 ...

  6. 泛型的类型擦除后,fastjson反序列化时如何还原?

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 哈喽大家好啊,我是Hydra~ 在前面的文章中,我们讲过Java中泛型的类型擦除,不过有小伙伴在后台留言提出了一个问题,带有泛型的实体的反序列化 ...

  7. 【转载】深入浅出SQL Server中的死锁

    essay from:http://www.cnblogs.com/CareySon/archive/2012/09/19/2693555.html 简介 死锁的本质是一种僵持状态,是多个主体对于资源 ...

  8. Laravel-手机短信验证码-阿里云

    1.composer require alibabacloud/client2.App\Service\AliyunSms.php <?php namespace App\Service; us ...

  9. MySQL Performance Schema详解

    MySQL的performance schema 用于监控MySQL server在一个较低级别的运行过程中的资源消耗.资源等待等情况. 1 performance schema特点 提供了一种在数据 ...

  10. ArcMap操作随记(5)

    1.[栅格转面]等工具的使用 若栅格数据为浮点型,需使用[转为整型]工具,将栅格转为整型,再进行操作. 2.人口密度分布趋势图 使用[核密度分析]工具,也可尝试插值 3.点要素做面 [点集转线][要素 ...