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

如何在Python与JS中实现带百分比的进度条?及Python服务端与Web GUI间测试进度高效更新方案咨询

Great question! Let’s split this into two clear parts: building progress bars with percentage displays, and optimizing the test progress update flow between your Python backend and JS frontend.


1. Building Progress Bars with Percentage Display

Python (CLI/Console)

For console-based progress bars, tqdm is the most convenient and efficient option, but you can also roll your own if you want to avoid third-party dependencies.

  • Using tqdm (Recommended)
    It handles percentage calculation, dynamic updates, and even estimated time remaining out of the box:

    from tqdm import tqdm
    import time
    
    total_tests = 50
    # Iterate through tests with a progress bar
    for _ in tqdm(range(total_tests), desc="Running Tests", unit="test"):
        time.sleep(0.1)  # Simulate test execution time
    
  • Custom Implementation
    If you prefer no external libraries, this simple function will update a progress line in the console:

    import sys
    import time
    
    def update_progress(current, total):
        percent = (current / total) * 100
        # Overwrite the current line to avoid cluttering output
        sys.stdout.write(f"\rProgress: {percent:.1f}% | Completed: {current}/{total}")
        sys.stdout.flush()
    
    total_tests = 50
    for i in range(total_tests):
        time.sleep(0.1)
        update_progress(i + 1, total_tests)
    print("\nAll tests finished!")
    

JavaScript (Browser GUI)

For your web-based GUI, you can build a clean, animated progress bar with HTML/CSS/JS:

  • HTML Structure

    <div class="progress-wrapper">
      <div class="progress-bar" id="testProgressBar"></div>
      <span id="progressLabel">0% Complete</span>
    </div>
    
  • CSS Styling

    .progress-wrapper {
      width: 400px;
      height: 25px;
      border-radius: 12px;
      border: 1px solid #ddd;
      position: relative;
      margin: 20px 0;
      overflow: hidden;
    }
    
    .progress-bar {
      height: 100%;
      background-color: #2563eb;
      width: 0%;
      transition: width 0.2s ease; /* Smooth animation */
    }
    
    #progressLabel {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      font-size: 14px;
      color: #333;
      font-weight: 500;
    }
    
  • JS Update Logic

    function updateTestProgress(current, total) {
      const percent = Math.round((current / total) * 100);
      const bar = document.getElementById('testProgressBar');
      const label = document.getElementById('progressLabel');
    
      bar.style.width = `${percent}%`;
      label.textContent = `${percent}% Complete (${current}/${total})`;
    }
    
    // Example: Simulate updates from backend
    let completed = 0;
    const total = 50;
    const interval = setInterval(() => {
      completed++;
      updateTestProgress(completed, total);
      if (completed === total) clearInterval(interval);
    }, 100);
    

2. Optimizing Test Progress Updates Between Backend and Frontend

Your initial approach (count total tests upfront + send per-test updates) works, but there are ways to reduce runtime overhead and improve efficiency, especially with large numbers of test cases:

a. Use WebSockets Instead of HTTP Requests/Threads

HTTP has significant overhead for frequent small updates (handshakes, headers, connection teardown). WebSockets establish a persistent, bidirectional connection, making them perfect for real-time progress updates.

  • Python Backend (with websockets library)

    import asyncio
    import websockets
    import json
    from threading import Thread
    
    total_tests = 0
    completed_tests = 0
    
    async def handle_client(websocket):
        global completed_tests
        # First, send the total test count to the frontend
        await websocket.send(json.dumps({"type": "total", "data": total_tests}))
        
        # Simulate test execution (replace with your actual test logic)
        for _ in range(total_tests):
            await asyncio.sleep(0.1)  # Test run time
            completed_tests += 1
            # Send progress update
            await websocket.send(json.dumps({"type": "update", "data": completed_tests}))
        
        # Notify frontend when all tests are done
        await websocket.send(json.dumps({"type": "done", "data": "All tests completed!"}))
    
    def start_ws_server():
        start_server = websockets.serve(handle_client, "localhost", 8765)
        asyncio.get_event_loop().run_until_complete(start_server)
        asyncio.get_event_loop().run_forever()
    
    # Start WebSocket server in a background thread
    Thread(target=start_ws_server).start()
    
    # Example: Count total tests from config files
    def count_total_from_configs(config_files):
        global total_tests
        total_tests = sum(len(config.get("tests", [])) for config in config_files)
    
  • JS Frontend

    const ws = new WebSocket('ws://localhost:8765');
    let totalTests = 0;
    
    ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      switch(data.type) {
        case "total":
          totalTests = data.data;
          break;
        case "update":
          updateTestProgress(data.data, totalTests);
          break;
        case "done":
          alert(data.data);
          ws.close();
          break;
      }
    };
    
    ws.onerror = (error) => console.error("WebSocket error:", error);
    

b. Batch Updates for High-Volume Tests

If you have thousands of test cases, even WebSocket messages can add up. Instead of sending an update per test, batch updates every N tests (e.g., 10 or 50) to cut down on communication overhead:

# Modify backend test loop to send batch updates
batch_size = 10
for i in range(total_tests):
    await asyncio.sleep(0.1)
    completed_tests += 1
    # Send update only when batch is full or all tests are done
    if completed_tests % batch_size === 0 or completed_tests === total_tests:
        await websocket.send(json.dumps({"type": "update", "data": completed_tests}))

Users won’t notice a meaningful delay, and you’ll drastically reduce the number of messages sent.

c. Avoid Unnecessary Threads (Use Async Where Possible)

If your backend uses an async framework like FastAPI or aiohttp, you don’t need separate threads to send progress updates. Integrate the WebSocket logic directly into your async test execution flow to eliminate thread-switching overhead.

d. Validate Total Test Count Upfront

Make sure your config parsing logic handles edge cases (empty test lists, malformed JSON, missing fields) to avoid incorrect total counts:

def count_total_from_configs(config_files):
    total = 0
    for config in config_files:
        if isinstance(config.get("tests"), list):
            total += len(config["tests"])
        else:
            print(f"Warning: Invalid config - missing or non-list 'tests' field")
    return total

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:37:41