You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

部署在Modal上的Streamlit文件上传器返回400错误(本地正常)

解决Modal部署Streamlit时st.file_uploader()返回400 Bad Request的问题

问题根源

出现该错误的核心原因包括:

  • Streamlit在容器化环境下未启用无头模式,导致内部上传API逻辑异常
  • 未显式指定Streamlit的上传临时目录,与Modal的临时存储路径不匹配
  • 使用subprocess.Popen启动Streamlit是非阻塞模式,可能引发进程管理异常

修复步骤

1. 修正Modal中Streamlit的启动配置

修改modal_app.pyrun函数,调整启动命令并确保进程稳定运行:

@app.function()
@modal.web_server(8000)
def run():
    cmd = [
        "streamlit", "run", "/root/streamlit_app.py",
        "--server.port", "8000",
        "--server.enableCORS=false",
        "--server.headless=true",  # 容器环境必需参数
        "--server.upload_dir=/tmp"  # 指定上传文件存储目录
    ]
    subprocess.run(cmd, check=True)  # 用run替代Popen,确保进程阻塞运行

同时需要补充模型文件的镜像添加步骤(当前配置缺失):

image = (
    modal.Image.debian_slim(python_version="3.12")
    .apt_install("libgl1", "libglib2.0-0", "ffmpeg")
    .uv_pip_install("streamlit", "ultralytics", "opencv-python", "supabase", "python-dotenv")
    .add_local_file("src/streamlit_app.py", "/root/streamlit_app.py")
    .add_local_file("../.env", "/root/.env")
    .add_local_file("path/to/your/best.pt", "/root/best.pt")  # 添加模型文件到镜像
)

2. 优化Streamlit应用的临时文件处理

简化streamlit_app.py的临时文件逻辑,确保文件写入到指定目录:

import streamlit as st
from ultralytics import YOLO
import tempfile, os
from dotenv import load_dotenv

load_dotenv("/root/.env")

st.title("🦺 PPE Detection App")

uploaded_file = st.file_uploader("Upload an image", type=["jpg", "png"])
if uploaded_file:
    # 在/tmp目录创建临时文件,避免路径权限问题
    with tempfile.NamedTemporaryFile(dir="/tmp", suffix=os.path.splitext(uploaded_file.name)[1], delete=False) as temp_file:
        temp_file.write(uploaded_file.getbuffer())
        temp_path = temp_file.name

    model = YOLO("/root/best.pt")
    results = model.predict(source=temp_path, save=True, project="/tmp", name="detections")
    st.success("✅ Detection complete!")
    
    # 可选:检测完成后清理临时文件
    os.unlink(temp_path)

3. 关键配置说明

  • --server.headless=true:容器化部署Streamlit的必需参数,禁用GUI相关组件,避免内部API异常
  • --server.upload_dir=/tmp:强制Streamlit将上传文件存储到Modal允许写入的临时目录,解决路径权限问题
  • subprocess.run:替代Popen确保进程持续运行,符合Modal的web服务托管要求

内容的提问来源于stack exchange,提问作者Tommie

火山引擎 最新活动