Streamlit下载按钮点击触发重运行,下载延迟问题求助
问题原因
你的问题核心是对Streamlit的运行机制理解有误:Streamlit是基于重运行的框架,任何组件交互(比如按钮点击)都会触发整个脚本从头重新执行一遍。
原代码里,你用st.button('Download QR Code')控制st.download_button的渲染——第一次点击这个按钮时,脚本重运行,此时st.button()返回True,才会渲染出download_button;第二次点击新出现的download_button才会触发下载。这就是需要点击两次的根本原因。
根本不需要额外的触发按钮,st.download_button本身就是可直接点击触发下载的组件,把它直接放在二维码生成后的分支里即可:
import streamlit as st import qrcode from io import BytesIO from PIL import Image def generate_qr_code(link): # Generate QR Code qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=2, ) qr.add_data(link) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") return img def download_qr_code(img): # Convert PIL image to bytes img_bytes = BytesIO() img.save(img_bytes, format='PNG') img_bytes.seek(0) return img_bytes st.title("QR Code Generator") link = st.text_input("Enter a link:") if link: qr_img = generate_qr_code(link) # 生成一次字节数据,避免重复转换 qr_bytes = download_qr_code(qr_img) st.image(qr_bytes, caption='Generated QR Code', width=300) # 直接显示下载按钮,点击即可触发下载 st.download_button( label="Download QR Code", data=qr_bytes, file_name='qr_code.png', mime='image/png' )
优化:用
st.session_state缓存生成结果(可选) 如果想避免每次页面重运行时重复生成二维码和字节数据,可以用st.session_state缓存结果,只有当链接变化时才重新生成:
import streamlit as st import qrcode from io import BytesIO from PIL import Image def generate_qr_code(link): # Generate QR Code qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=2, ) qr.add_data(link) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") return img def download_qr_code(img): # Convert PIL image to bytes img_bytes = BytesIO() img.save(img_bytes, format='PNG') img_bytes.seek(0) return img_bytes st.title("QR Code Generator") link = st.text_input("Enter a link:") # 初始化session_state变量 if "last_link" not in st.session_state: st.session_state.last_link = "" if "qr_bytes" not in st.session_state: st.session_state.qr_bytes = None if link: # 只有当链接变化时,才重新生成二维码和字节数据 if link != st.session_state.last_link: qr_img = generate_qr_code(link) st.session_state.qr_bytes = download_qr_code(qr_img) st.session_state.last_link = link # 直接使用缓存的字节数据 st.image(st.session_state.qr_bytes, caption='Generated QR Code', width=300) st.download_button( label="Download QR Code", data=st.session_state.qr_bytes, file_name='qr_code.png', mime='image/png' )
关键知识点解释
- Streamlit重运行机制:任何用户交互(按钮点击、输入框输入等)都会触发整个脚本从头执行,所有组件都是在每次重运行时重新渲染的。
st.download_button的特性:这个组件本身集成了“显示按钮+触发下载”的功能,点击它时会直接向浏览器发送下载数据,不会触发页面重运行(这是少数几个不会触发重运行的组件之一)。st.session_state的用法:用来在多次重运行之间存储变量,避免重复计算或状态丢失。这里用它缓存二维码的字节数据,只有当输入的链接变化时才重新生成。
内容的提问来源于stack exchange,提问作者Ali Malek
相关产品推荐
相关产品推荐

