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. C#foreach 本质( 鸭子类型遍历)

    探讨关于C#中Foreach的本质 要实现foreach需要满足什么条件? 只要类中实现类中的GetEnumerator()方法.MoveNext()方法.Current属性(俗称鸭子类型)都可以使用 ...

  2. 每日一算法之two sum

    题目如下:首先准备一个数组,[1,2,8,4,9]  然后输入一个6,找出数组两项之和为6的两个下标. 啥也不想,马上上代码,这个太简单了, static int[] twoSum(int[] num ...

  3. spring的依赖注入的四种方式,数组与集合注入;引用注入;内部bean注入

    三种注入方式 第一种: 基于构造函数 hi.java (bean) package test_one; public class hi { private String name; public hi ...

  4. 洛谷训练P1008(循环+暴力)

    1 #include<stdio.h> 2 #include<string.h> 3 int a[10]; 4 int main(){ 5 for (int x=123;x&l ...

  5. MyBatis动态 order by 排序不生效解决方法

    使用Mybatis在做一个项目时,发现需要动态的去做一个排序功能,于是乎有了下面XXXMapper.xml代码 <if test="order!=null and !order.isE ...

  6. css样式之浮动

    什么是浮动? 添加了浮动的的元素会脱离正常的文档流. 浮动的特点: 1.可以让块级元素排在同一排 2.可以让行属性标签支持所有的css样式 3.遇到相邻的浮动元素或者父级元素会停下来 4.浮动会影响其 ...

  7. linux tr命令实现windows文本格式与linux文本格式间的转换

    tr 命令 转换和删除字符 选项: -d --delete:删除字符 -s --squeeze-repeats:把连续重复的字符以一个字符表示,即去重 -c –C --complement:取字符集的 ...

  8. tensorflow源码解析之common_runtime-executor-下

    目录 核心概念 executor.h Executor NewLocalExecutor ExecutorBarrier executor.cc structs GraphView ExecutorI ...

  9. Net6 Configuration & Options 源码分析 Part1

    Net6 Configuration & Options 源码分析 Part1 在Net6中配置系统一共由两个部分组成Options 模型与配置系统.它们是两个完全独立的系统. 第一部分主要记 ...

  10. Python入门随记(4)

    在涉及一些实际问题,会碰到概率论等相关领域的知识,自然少不了矩阵运算,以下是Python中关于矩阵的简单操作: 1.常用库numpy import numpy as np 2.随机生成矩阵 a=np. ...