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.