Skip to content

Instantly share code, notes, and snippets.

@lwcorp
Last active March 21, 2025 01:55
Show Gist options
  • Save lwcorp/7d54223bacc4dfc272762686c0159c80 to your computer and use it in GitHub Desktop.
Save lwcorp/7d54223bacc4dfc272762686c0159c80 to your computer and use it in GitHub Desktop.
Run Python code via cPanel without restarting or timing out, and also use Flask
import os
import json
import html
import signal
from datetime import datetime
from flask import Flask, render_template, request, jsonify
# Check if `signal.alarm` is supported
signal_supported = hasattr(signal, 'SIGALRM')
if signal_supported:
class TimeoutException(Exception):
pass
def timeout_handler(signum, frame):
raise TimeoutException("Request took too long!")
# Register the timeout signal handler
signal.signal(signal.SIGALRM, timeout_handler)
# Edit this part - start
template_folder = 'public_html/example'
template_file = 'index.html'
# Edit this part - end
app = Flask(__name__,
template_folder=template_folder,
static_folder=template_folder + '/static')
@app.route('/', methods=['GET', 'POST'])
def flaskFormProccessing():
if __name__ == '__main__' and request.method == 'GET':
try:
return render_template(template_file)
except Exception as e:
print(str(e))
# Edit this part - start
# Process the form nomally with Flask, for example firstName = request.form.get('first-name') and return jsonify({'key1': value2, 'key2': value2})
pass
# Edit this part - end
# This is the only function that gets loaded initially so everything goes through here first
def application(environ, start_response):
# Before anything else, get the app restarted automatically to support any code changes
restart_file = os.path.join(os.path.dirname(__file__), 'tmp/restart.txt')
if os.path.exists(restart_file):
current_time = datetime.now().timestamp()
os.utime(restart_file, (current_time, current_time))
# Set a realistic timeout instead of relying on the server's timeout
if signal_supported:
signal.alarm(30)
try:
# Avoid waiting indefinitely (or until a timeout) if a form was submitted without fields
content_length = int(environ.get('CONTENT_LENGTH', 0))
if content_length == 0:
# Just an example, as it depends on what your form expects - the example assumes the form uses Fetch API or Ajax
start_response('200 OK', [('Content-Type', 'application/json')])
return [json.dumps({'output': 'No form values passed', 'success': False}).encode()]
# Instead of checking form fields with manual methods, just send to Flask
with app.test_request_context(base_url=environ.get('wsgi.url_scheme', 'http') + '://' + environ.get('HTTP_HOST', ''), environ_overrides=environ):
# Let Flask handle the request
response = app.full_dispatch_request()
# Convert Flask's response to WSGI response
start_response(
response.status,
[(k, v) for k, v in response.headers]
)
return [response.get_data()]
except TimeoutException:
# Just an example, as it depends on what your form expects - the example assumes the form uses Fetch API or Ajax
start_response('504 Gateway Timeout', [('Content-Type', 'application/json')])
return [json.dumps({'output': 'Request timed out', 'success': False}).encode()]
except Exception as e:
# Just an example, as it depends on what your form expects - the example assumes the form uses Fetch API or Ajax
start_response('500 Internal Server Error', [('Content-Type', 'application/json')])
return [json.dumps({'output': str(e), 'success': False}).encode()]
finally:
# The timer finished serving its purpose
if signal_supported:
signal.alarm(0) # Disable the alarm
if __name__ == '__main__':
# Only use debug mode when running locally
is_production = os.environ.get('PRODUCTION', 'false').lower() == 'true'
if is_production:
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
else:
app.run(debug=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment