flask_socker and pyinstaller ValueError: Invalid async_mode specified issue

121 views Asked by At

I am trying to create a pyinstaller .exe of a flask application which uses flask_socketio. But when I run the app.exe created by pyinstaller, I am facing the following error:

Traceback (most recent call last):
  File "app.py", line 8, in <module>
    socketio = SocketIO(app)
               ^^^^^^^^^^^^^
  File "flask_socketio\__init__.py", line 187, in __init__
  File "flask_socketio\__init__.py", line 243, in init_app
  File "socketio\base_server.py", line 31, in __init__
  File "engineio\base_server.py", line 81, in __init__
ValueError: Invalid async_mode specified
[31708] Failed to execute script 'app' due to unhandled exception!

I tried adding engineio.async_eventlet and engineio.async_drivers.eventlet in the hidden imports sections of the app.spec file (followed this link). But this did not work.

I then tried adding from engineio.async_drivers import gevent in app.py file (followed this link), it does seem to run the application, but I dont believe sockets seem to be working as there was no real time update happening on the webpage.

Here are my code files:

app.py

from time import sleep
from datetime import datetime
from flask import Flask, render_template
from flask_socketio import SocketIO, emit

app = Flask(__name__)
socketio = SocketIO(app)

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


@socketio.on('start_streaming')
def start_streaming(data):
    
    selected_msg_type = data.get('msg_type')

    # Print the selected message type
    print(f"Selected Message Type: {selected_msg_type}")
    
    ls = [f'File{i}.txt' for i in range(1, 11)]

    max_num = len(ls)
    for i in range(0, max_num):
        emit('new_data', {'value': f'[{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}] - {ls[i]}: Done', 'progress': int(((i+1)/max_num)*100)})
        sleep(1)

    # After the comparison is completed, emit the 'show_results' event
    results = f"Total cases: {len(ls)}"
    emit('show_results', results)

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

and index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Streaming Data</title>
    <link rel="stylesheet" href="../static/css/bootstrap.min.css">
    <style>
        body {
            font-family: 'Arial', sans-serif;
            background-color: #f4f4f4;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            height: 100%;
        }

        #mainbox {
            width: 80%;
            margin-top: 5%;
            margin-bottom: 5%;
            display: flex;
            flex-direction: column;
            align-items: center;
            border-radius: 10px;
            box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.4);
            padding: 30px;
            max-width: 42%;
            background-color: rgba(255, 255, 255, 0.9);
        }

        #progress-bar-container {
            display: none;
            /* Center the progress bar horizontally */
            justify-content: center;
            align-items: center;
            /* Center the progress bar vertically */
            width: 95%;
            /* width control */
            margin-top: 20px;
            /* Adjusted margin top */
            background-color: #333333;
            border-radius: 5px;
            box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.4);
            z-index: 1000;
        }

        #progress-bar {
            height: 3vh;
            background-color: #e0e0e0;
            width: 100%;
            position: relative;
            border-radius: 5px;
            overflow: hidden;
        }

        #progress-fill {
            height: 100%;
            background-color: #3498db;
            width: 0;
            border-radius: 5px;
            transition: width 0.3s ease-in-out;
        }

        #progress-text {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: #ffffff;
        }

        iframe {
            width: 100%;
            height: 20vh;
            border: none;
            background-color: #F0F0F0;
            color: #000000;
            font-size: 14px;
            overflow-y: scroll;
            margin-bottom: 20px;
            border-radius: 10px;
        }

        .output-container {
            width: 95%;
            /* width control */
            margin-top: 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        h1 {
            text-align: center;
            margin-bottom: 10px;
            /* Added margin between heading and progress bar */
        }

        button {
            margin-top: 10px;
            margin-bottom: 10px;
            padding: 10px;
            font-size: 16px;
            background-color: #4caf50;
            color: #ffffff;
            border: none;
            cursor: pointer;
        }

        #completeButton {
            width: 10%;
            display: none;
            /* Initially hidden */
        }

        .disabled {
            cursor: not-allowed;
            background-color: #cccccc;
        }

        .line {
            margin-top: 10px;
            margin-bottom: 10px;
            width: 95%;
            height: 1px;
            border-top: 1px solid #ccc;
        }

        #popup {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            padding: 20px;
            background-color: rgba(255, 0, 0, 0.5);
            /* Transparent red background */
            color: #ffffff;
            /* White text */
            border-radius: 10px;
            box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.8);
            text-align: center;
            width: 10%;
            /* Set the desired width */
        }

        #logsParagraph,
        #runReportParagraph {
            font-size: 18px;
            margin-bottom: 10px;
            margin-top: 10px;
            font-family: 'Arial', sans-serif;
            text-align: left; /* Add this line to align the text to the left */
        }

    </style>
</head>

<body>
    <div id="mainbox">
        <h1>Check Message</h1>
        <div class="line"></div>

        <div style="display: flex; align-items: center; justify-content: flex-start; width: 100%; margin-top:10px; margin-bottom:10px;padding: 20px;">
            <label class="form-label" style="margin-right: 0px; width:25%; font-size:20px;">Message type:</label>
            <select class="form-control" id="MsgType" name="MsgType" onchange="updateLabels()">
                <option value="opt1">Option1</option>
                <option value="opt2">Option2</option>
                <option value="opt3">Option3</option>
                <option value="opt4">Option4</option>
            </select>
        </div>

        
        <div id="progress-bar-container">
            <div id="progress-bar">
                <div id="progress-fill"></div>
                <div id="progress-text">0%</div>
            </div>
        </div>

        <div class="output-container">
            <p id="logsParagraph" style="display: none;margin-top:10px; position: relative; margin-right:94%;">Logs:</p>
            <!-- Updated: Moved iframe inside the output-container and adjusted its width -->
            <iframe id="streamFrame" style="display: none; width: 100%; "></iframe>
            <p id="runReportParagraph" style="display: none;margin-top:10px;margin-bottom:10px; margin-right:79%;">Execution Report:</p>
            <div class="result-container" style="display: none; width: 100%; background-color:#F0F0F0; border-radius:10px;margin-bottom:30px;"></div>
            <button id="startButton" class="btn btn-primary btn-block" style="width:30%" onclick="startStreaming()">Start
                Comparison</button>
            <button id="completeButton" class="btn btn-primary btn-block" style="width:30%">View Results</button>
        </div>
    </div>
    <div id="popup"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.3/socket.io.js"></script>
    <script>
        var socket = io.connect('http://' + document.domain + ':' + location.port);
        var progressBarContainer = document.getElementById('progress-bar-container');
        var progressBar = document.getElementById('progress-bar');
        var progressFill = document.getElementById('progress-fill');
        var progressText = document.getElementById('progress-text');
        var startButton = document.getElementById('startButton');
        var completeButton = document.getElementById('completeButton');
        var streamFrame = document.getElementById('streamFrame');
        var logsParagraph = document.getElementById('logsParagraph');
        var runReportParagraph = document.getElementById('runReportParagraph');
        var popup = document.getElementById('popup');

        socket.on('connect', function () {
            console.log('Socket connected');
            // Hide the result container initially
            var resultContainer = document.querySelector('.result-container');
            resultContainer.style.display = 'none';
        });

        // Pop up
        socket.on('empty_list', function (data) {
            // Show the pop-up with the received message
            showPopup(data.message);
            // Hide progress bar and iframe
            progressBarContainer.style.display = 'none';
            streamFrame.style.display = 'none';
            logsParagraph.style.display = 'none'; // Hide logs paragraph
            // Enable the "Start Comparison" button after 3 seconds
            setTimeout(function () {
                startButton.disabled = false;
                startButton.classList.remove('disabled');
                startButton.innerText = 'Start Comparison';
            }, 1000);
        });

        // Inside the socket.on('new_data', ...) function
        socket.on('show_results', function (results) {
            // Display results below the iframe
            var resultContainer = document.querySelector('.result-container');
            resultContainer.innerHTML = '<pre style="margin:10px;font-family:Courier New;font-size">' + results + '</pre>';
            resultContainer.style.display = 'block';
            runReportParagraph.style.display = 'block'; // Show run report paragraph
        });

        socket.on('new_data', function (data) {
            var output = streamFrame.contentDocument.body;
            var item = document.createElement('p');
            item.style.color = '#000000';
            item.textContent = data.value;
            output.appendChild(item);

            // Scroll to the bottom of the iframe
            streamFrame.contentWindow.scrollTo(0, output.scrollHeight);

            // Update progress bar
            progressFill.style.width = data.progress + '%';
            progressText.textContent = data.progress + '%';

            // Change color to green when completed
            if (data.progress === 100) {
                progressFill.style.backgroundColor = '#2ecc71'; /* Green color */

                // Enable the button when progress is completed
                startButton.disabled = false;
                startButton.classList.remove('disabled');
                startButton.innerText = 'Run comparison again';

                // Show the complete button
                completeButton.style.display = 'inline';
            } else {
                // Disable the button while progress is running
                startButton.disabled = true;
                startButton.classList.add('disabled');
                logsParagraph.style.display = 'block'; // Show logs paragraph
                runReportParagraph.style.display = 'none'; // Hide run report paragraph
                // Hide the complete button while progress is not completed
                completeButton.style.display = 'none';
            }

            // Show the progress bar container
            progressBarContainer.style.display = 'block';
        });


        function reloadPage() {
            location.reload();
        }

        function showPopup(message) {
            popup.innerHTML = message;
            popup.style.display = 'block';
            // Hide the pop-up after 3 seconds (adjust the timeout as needed)
            setTimeout(function () {
                popup.style.display = 'none';
            }, 1000);
        }

        function startStreaming() {
        
            var startButton = document.getElementById('startButton');
            
            var msgTypeSelect = document.getElementById('MsgType');
            var selectedMsgType = msgTypeSelect.value;
            
            startButton.innerText = 'Run Comparison Again';
            startButton.onclick = reloadPage;
            // Reset progress bar
            progressFill.style.width = '0%';
            progressText.textContent = '0%';
            progressFill.style.backgroundColor = '#3498db'; /* Reset to blue color */

            // Disable the button while progress is running
            startButton.disabled = true;
            startButton.classList.add('disabled');
            logsParagraph.style.display = 'none'; // Hide logs paragraph

            // Show the progress bar container
            progressBarContainer.style.display = 'block';

            // Show the iframe after clicking the "Start Streaming" button
            streamFrame.style.display = 'block';

            streamFrame.contentDocument.body.style.fontFamily = "Courier New";
            socket.emit('start_streaming', {'msg_type': selectedMsgType});

            
        }
        
        
    </script>
</body>

</html>

Can someone please help me resolve this issue? Thank you.

0

There are 0 answers