如何在Streamlit应用中实现学生成绩存储、计算及PDF导出?
学生成绩录入Streamlit应用解决方案
现有代码(原生Python)
import sys import pandas as pd batch_size = int(input("how many students are there in your class?")) if batch_size > 10: sys.exit("Batch size cannot be greater than 10") print(batch_size) D={} # Add student information # to the dictionary for i in range(1, batch_size + 1): roll = i marks = int(input('Enter Marks: ')) D[roll] = marks print(D) df=pd.DataFrame(D) print(df)
核心问题
- 如何在Streamlit中实现批量录入多名学生的学号及成绩,并完成数据存储?
- 如何将计算后的DataFrame结果导出为PDF?
一、批量录入与数据存储实现
Streamlit依赖组件交互而非原生input(),结合session_state实现会话内数据暂存,若需持久化可结合云存储或本地文件导出。
完整录入代码示例
import streamlit as st import pandas as pd # 初始化会话级存储,避免页面刷新丢失数据 if 'students' not in st.session_state: st.session_state.students = [] st.title("学生成绩录入系统") # 设定班级学生数量 batch_size = st.number_input("请输入班级学生数量", min_value=1, max_value=10, step=1) # 用表单实现批量提交 with st.form("成绩录入表单"): st.subheader(f"录入{int(batch_size)}名学生信息") roll_inputs = [] marks_inputs = [] # 动态生成学号、成绩输入框 for idx in range(int(batch_size)): col1, col2 = st.columns(2) with col1: roll = st.text_input(f"学生{idx+1}学号", key=f"roll_{idx}") with col2: marks = st.number_input(f"学生{idx+1}成绩", min_value=0, max_value=100, key=f"marks_{idx}") roll_inputs.append(roll) marks_inputs.append(marks) submit_btn = st.form_submit_button("提交成绩") # 提交后存储数据 if submit_btn: # 过滤空学号的无效输入 valid_entries = [(r, m) for r, m in zip(roll_inputs, marks_inputs) if r.strip()] st.session_state.students.extend(valid_entries) st.success(f"成功录入{len(valid_entries)}条成绩数据!") # 展示已录入数据并添加计算列 if st.session_state.students: df = pd.DataFrame(st.session_state.students, columns=["学号", "成绩"]) # 示例计算列:是否及格 df["是否及格"] = df["成绩"].apply(lambda x: "是" if x >=60 else "否") st.subheader("学生成绩统计表") st.dataframe(df, use_container_width=True)
数据存储方案
- 会话内暂存:用
st.session_state,仅当前浏览器会话有效,关闭页面数据清空 - 持久化存储:
- 让用户导出CSV保存,下次上传继续编辑(可添加
st.download_button实现CSV导出) - 对接云数据库(如Firebase、Supabase)或在线表格(如Google Sheets),需额外配置权限
- 让用户导出CSV保存,下次上传继续编辑(可添加
二、导出计算结果为PDF
使用fpdf2库生成PDF,结合Streamlit的download_button实现一键下载。
完整导出代码整合
在上述代码的基础上,添加以下部分:
from fpdf import FPDF import io def generate_score_pdf(df): pdf = FPDF() pdf.add_page() # 设置字体与标题 pdf.set_font("Arial", 'B', size=14) pdf.cell(200, 15, txt="学生成绩计算报告", ln=True, align='C') pdf.ln(5) # 写入表头 pdf.set_font("Arial", 'B', size=12) headers = df.columns.tolist() col_width = 200 / len(headers) for header in headers: pdf.cell(col_width, 10, txt=header, border=1, align='C') pdf.ln() # 写入数据行 pdf.set_font("Arial", size=12) for _, row in df.iterrows(): for item in row: pdf.cell(col_width, 10, txt=str(item), border=1, align='C') pdf.ln() # 添加统计信息 pdf.ln(10) pdf.set_font("Arial", 'B', size=12) avg_score = df["成绩"].mean() pdf.cell(200, 10, txt=f"班级平均分: {avg_score:.2f}", ln=True, align='R') # 转换为字节流供下载 return pdf.output(dest='S').encode('latin-1') # 在展示DataFrame后添加下载按钮 if st.session_state.students: # ... 前面的df处理代码 ... pdf_bytes = generate_score_pdf(df) st.download_button( label="下载成绩报告PDF", data=pdf_bytes, file_name="学生成绩报告.pdf", mime="application/pdf" )
部署依赖配置
在Streamlit Cloud部署时,需创建requirements.txt文件,包含以下依赖:
streamlit pandas fpdf2
内容的提问来源于stack exchange,提问作者Krishna
相关产品推荐
相关产品推荐

