You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过网页按钮运行Python脚本并实现实时输出的技术需求

嗨凯文!很高兴能帮到你——比利时的朋友😉。你遇到的这个问题其实很常见:当后端脚本运行时间较长时,传统的同步请求会让页面一直处于加载状态,直到脚本完全跑完才返回所有结果。要实现实时输出,我们需要用异步通信的方式,让服务器一边运行脚本,一边把输出推送到网页上。下面给你两个实用的实现方案,你可以根据需求选择:

方案一:Server-Sent Events(SSE)——适合单向实时输出

SSE是HTML5原生支持的特性,专门用来实现服务器向客户端单向推送消息,非常契合你这种只需要把脚本输出实时展示的场景,实现起来也最简单。

后端(Python Flask示例)

from flask import Flask, Response
import subprocess
import time

app = Flask(__name__)

def stream_script_output():
    # 替换成你的脚本路径和运行命令
    proc = subprocess.Popen(
        ["python", "your_long_running_script.py"],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,  # 把错误输出也合并到标准输出
        text=True
    )

    # 逐行读取脚本输出,实时推送给前端
    for line in iter(proc.stdout.readline, ''):
        if line:
            # SSE的消息格式必须是 "data: 内容\n\n"
            yield f"data: {line.strip()}\n\n"
            # 可选:加一点小延迟,方便看清实时输出的过程
            time.sleep(0.1)
    
    # 等待脚本运行结束,返回完成提示
    proc.wait()
    yield "data: 脚本运行完成!🎉\n\n"

@app.route('/start_script')
def start_script():
    return Response(
        stream_script_output(),
        mimetype='text/event-stream'
    )

if __name__ == '__main__':
    # 必须开启threaded=True,否则Flask会被脚本阻塞,无法处理其他请求
    app.run(debug=True, threaded=True)

前端(HTML/JS)

<!DOCTYPE html>
<html>
<head>
    <title>实时脚本输出</title>
    <style>
        #output { margin-top: 20px; padding: 10px; border: 1px solid #ddd; }
    </style>
</head>
<body>
    <button onclick="startStreaming()">运行脚本</button>
    <div id="output"></div>

    <script>
        function startStreaming() {
            const outputDiv = document.getElementById('output');
            // 清空之前的输出
            outputDiv.innerHTML = '';

            // 创建SSE连接,请求后端的流接口
            const eventSource = new EventSource('/start_script');

            // 接收服务器推送的每一行输出
            eventSource.onmessage = function(event) {
                const line = document.createElement('p');
                line.textContent = event.data;
                outputDiv.appendChild(line);
                // 自动滚动到最新内容
                outputDiv.scrollTop = outputDiv.scrollHeight;
            };

            // 连接关闭(脚本运行结束)时的处理
            eventSource.onerror = function() {
                eventSource.close();
                const doneLine = document.createElement('p');
                doneLine.style.color = '#2ecc71';
                doneLine.style.fontWeight = 'bold';
                doneLine.textContent = '✅ 脚本已完成';
                outputDiv.appendChild(doneLine);
            };
        }
    </script>
</body>
</html>
方案二:WebSocket——适合双向交互(进阶需求)

如果之后你需要给运行中的脚本发送指令(比如暂停、调整参数),WebSocket会更合适,它支持双向通信。这里用Flask-SocketIO来实现:

后端(Python Flask-SocketIO)

首先需要安装依赖:pip install flask-socketio

from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import subprocess
import threading

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key-here'
socketio = SocketIO(app, cors_allowed_origins="*")

def run_script_in_thread():
    proc = subprocess.Popen(
        ["python", "your_long_running_script.py"],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        text=True
    )

    for line in iter(proc.stdout.readline, ''):
        if line:
            # 推送输出到前端
            socketio.emit('script_output', {'content': line.strip()})
            socketio.sleep(0.1)
    
    proc.wait()
    # 推送完成消息
    socketio.emit('script_finished', {'message': '脚本运行完成!'})

# 监听前端的"start_script"事件
@socketio.on('start_script')
def handle_start_script():
    # 在新线程中运行脚本,避免阻塞WebSocket服务
    threading.Thread(target=run_script_in_thread).start()

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    socketio.run(app, debug=True)

前端(HTML/JS)

<!DOCTYPE html>
<html>
<head>
    <title>实时脚本输出(WebSocket)</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
    <style>
        #output { margin-top: 20px; padding: 10px; border: 1px solid #ddd; }
    </style>
</head>
<body>
    <button onclick="startScript()">运行脚本</button>
    <div id="output"></div>

    <script>
        // 连接WebSocket服务器
        const socket = io();
        const outputDiv = document.getElementById('output');

        function startScript() {
            outputDiv.innerHTML = '';
            // 向后端发送"start_script"事件,触发脚本运行
            socket.emit('start_script');
        }

        // 接收脚本输出
        socket.on('script_output', function(data) {
            const line = document.createElement('p');
            line.textContent = data.content;
            outputDiv.appendChild(line);
            outputDiv.scrollTop = outputDiv.scrollHeight;
        });

        // 接收脚本完成消息
        socket.on('script_finished', function(data) {
            const doneLine = document.createElement('p');
            doneLine.style.color = '#2ecc71';
            doneLine.style.fontWeight = 'bold';
            doneLine.textContent = `✅ ${data.message}`;
            outputDiv.appendChild(doneLine);
        });
    </script>
</body>
</html>
重要注意事项
  • 确保你的Python脚本是逐行输出的:如果脚本里用了print,默认是行缓冲的,但如果有大量输出或者涉及到缓冲操作,记得加上flush=True,比如print("Hello World", flush=True),这样才能实时获取输出。
  • 生产环境部署:不要用Flask的debug模式,建议用Gunicorn配合eventlet/gevent来运行,比如gunicorn --worker-class eventlet -w 1 app:app(针对WebSocket方案),避免服务阻塞。
  • 脚本参数传递:如果需要给脚本传参数,可以在后端的接口里接收参数,再通过subprocess传递给脚本,比如subprocess.Popen(["python", "script.py", param1, param2])。

希望这些方案能帮到你!如果有哪里不清楚的,随时问我哦😎。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:25:45