I haven't found a way to set a handler to detect when a flask server is already running. Consider the following code snippet:
import flask
import requests
def on_start():
# send a request to the server, it's safe to do so
# because we know it's already running
r = requests.get("http://localhost:1234")
print(r.text) # hello world
app = flask.Flask(__name__)
#app.route("/")
def hello():
return "hello world"
app.run(port=1234, host="localhost", on_start=on_start)
The last line fails because on_start is not an argument of run, but hopefully you get the idea of what I'm trying to do. How can I do it?
What you can do is wrap the function that you want to kick off with before_first_request decorator as found here ==> http://flask.pocoo.org/docs/1.0/api/#flask.Flask.before_first_request
However, it won't get kicked off until someone makes a request to the server but you can do something like this:
import requests
import threading
import time
from flask import Flask
app = Flask(__name__)
#app.before_first_request
def activate_job():
def run_job():
while True:
print("Run recurring task")
time.sleep(3)
thread = threading.Thread(target=run_job)
thread.start()
#app.route("/")
def hello():
return "Hello World!"
def start_runner():
def start_loop():
not_started = True
while not_started:
print('In start loop')
try:
r = requests.get('http://127.0.0.1:5000/')
if r.status_code == 200:
print('Server started, quiting start_loop')
not_started = False
print(r.status_code)
except:
print('Server not yet started')
time.sleep(2)
print('Started runner')
thread = threading.Thread(target=start_loop)
thread.start()
if __name__ == "__main__":
start_runner()
app.run()
Details & Source via Google-fu: https://networklore.com/start-task-with-flask/
Related
I am trying to send data from server to flutter app using socketIO. Although I am able to connect and emit, the server is not able to send data to client side.
Server side code:
import cv2
import numpy as np
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
from threading import Lock,Timer as tmr
from engineio.payload import Payload
import base64
import io
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
someList = ['apple', 'peas', 'juice','orange']
i=0
#socketio.on('connect')
def connect():
print("a client connected")
#socketio.on('disconnect')
def disconnect():
print('Client disconnected')
#socketio.on('msg')
def handlemsg(msg):
print (msg)
socketio.send("msg from server")
#app.route('/')
def hello():
return "hii"
if __name__ == '__main__':
socketio.run(app,host= '0.0.0.0')
Client side (flutter)
#override
void initState() {
super.initState();
IO.Socket socket = IO.io('http://x.x.x.x:5000', <String, dynamic>{
'transports': ['websocket', 'polling']});
socket.connect();
socket.emit('msg', 'test');
socket.onConnect((_) {
print('connect');
socket.emit('msg', 'testing');
});
socket.onDisconnect((_) => print('disconnect'));
socket.on('*', (data) => print(data)); //nothing is printed
}
The result I get on the server-side:
a client connected
testing
However, I get no data on the client side. Where am I going wrong? Please help
I can't test it with flutter but I tested it with client create with python-socketio
Main problem can be that send() sends message with name "message" like emit("message", ...) but your on("msg", ...) expects message with name "msg", not "message".
So you should use emit("msg", ...) in Python and on("msg", ...) in flutter.
Or you should use send() in Python and on("message", ...) in flutter.
Other problem can be that it may need some time to send message and receive it - and it may need extra time after connecting and extra time befor disconnecting - at least in my example I had to sleep to get results.
Full working code.
I added more emit() with different names.
server.py
from flask import Flask
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
#socketio.on('connect')
def connect():
print("client connected")
#socketio.on('disconnect')
def disconnect():
print('client disconnected')
#socketio.on('question')
def handle_questio(msg):
print('question msg:', msg)
socketio.emit("answer", "msg from server")
#socketio.on('help')
def handle_help(msg):
print('help msg:', msg)
socketio.emit("support", "help from server")
#app.route('/')
def hello():
return "hii"
if __name__ == '__main__':
print('start')
socketio.run(app, host='0.0.0.0')
client.py
import socketio
sio = socketio.Client()
#sio.on('connect')
def connect():
print('connected')
#sio.on('disconnect')
def disconnect():
print('disconnected')
#sio.on('answer')
def answer(data):
print('answer:', data)
#sio.on('support')
def support(data):
print('support:', data)
# --- main ---
print('start')
sio.connect('http://localhost:5000')
print('sleep')
sio.sleep(1)
print('emit question')
sio.emit('question', {'foo': 'bar'})
print('emit help')
sio.emit('help', 'can you help me')
print('sleep')
sio.sleep(1)
sio.disconnect()
I'm creating a local app. I'd like to be able to shutdown the server from am api call, but do not have any success.
Here're some code:
# q.py
from multiprocessing import Queue
q = Queue()
def stop_server(*args, **kwargs):
q.put("EXTERMINATE")
# app.py
app = FastAPI()
#app.get("/kill")
def index(background_tasks: BackgroundTasks):
background_tasks.add_task(stop_server)
return {"killed": True}
# main.py
from q import q
def start_server():
uvicorn.run(app="app:app", host="127.0.0.1", port=8080)
if __name__ == "__main__":
server = Process(target=start_server)
server.start()
# sleep(5)
# q.put("EXTERMINATE")
# sleep(3)
while True:
msg = q.get()
if msg == "EXTERMINATE":
while server.is_alive():
server.terminate()
sleep(0.1)
server.join(timeout=1)
q.close()
break
Accessing "127.0.0.1:8080/kill" does nothing.
There is a commented block that manually put a message into the queue. If you uncomment the code, you should see the server terminated successfully.
So, how could I access the queue from inside a fastapi handler?
I have a schedule script running a job with:
schedule.every(3).seconds.do(jobCheckSmth)
while True:
schedule.run_pending()
time.sleep(1)
I wanted to use web interface to check on it's status instead of print() on the CLI with
run(host='localhost', port=80, debug=True)
But it blocks code execution so I have to Ctrl-C to break webserver loop to continue to run while loop
Bottle v0.12.18 server starting up (using WSGIRefServer())...
Listening on http://localhost:80/ Hit Ctrl-C to quit.
Here is an example that works really well for me using gevent to turn bottle into async. It's either this, or you have to run schedule in it's own thread outside of your bottle app. But honestly you should be doing this.
import gevent
from gevent import monkey,spawn as gspawn, sleep as gsleep, socket, signal_handler as sig
monkey.patch_all()
import signal
import arrow
from bottle import Bottle, static_file, get, post, request, response, template, redirect, hook, route, abort
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler
def start():
def start_thread():
set()
while 1:
try:
schedule.run_pending()
except:
logger.exception('Scheduler Exception')
gsleep(5) # This is the polling cycle for pending jobs
print('Scheduler Started...')
gspawn(start_thread)
def sample():
gspawn(jobCheckSmth)
def set():
# schedule.every(180).seconds.do(func)
schedule.every().day.at("00:00").do(sample)
logger.info('Started Schedule at {}'.format(arrow.now()))
#get('/')
def app():
return 'Hello World!'
if __name__ == '__main__':
scheduler.start()
botapp = bottle.app()
server = WSGIServer(("0.0.0.0", int(port)), botapp , handler_class=WebSocketHandler)
def shutdown():
print('Shutting down ...')
server.stop(timeout=60)
exit(signal.SIGTERM)
sig(signal.SIGTERM, shutdown)
sig(signal.SIGINT, shutdown)
server.serve_forever()
I'm trying to use Flask and SocketIO, i found this example where some random numbers are printed dynamically in real time on a webpage.
from flask_socketio import SocketIO, emit
from flask import Flask, render_template, url_for, copy_current_request_context
from random import random
from time import sleep
from threading import Thread, Event
__author__ = 'slynn'
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
app.config['DEBUG'] = True
#turn the flask app into a socketio app
socketio = SocketIO(app)
#random number Generator Thread
thread = Thread()
thread_stop_event = Event()
class RandomThread(Thread):
def __init__(self):
self.delay = 1
super(RandomThread, self).__init__()
def randomNumberGenerator(self):
"""
Generate a random number every 1 second and emit to a socketio instance (broadcast)
Ideally to be run in a separate thread?
"""
#infinite loop of magical random numbers
print("Making random numbers")
while not thread_stop_event.isSet():
number = round(random()*10, 3)
print(number)
socketio.emit('newnumber', {'number': number}, namespace='/test')
sleep(self.delay)
def run(self):
self.randomNumberGenerator()
#app.route('/')
def index():
#only by sending this page first will the client be connected to the socketio instance
return render_template('index.html')
#socketio.on('connect', namespace='/test')
def test_connect():
# need visibility of the global thread object
global thread
print('Client connected')
#Start the random number generator thread only if the thread has not been started before.
if not thread.isAlive():
print("Starting Thread")
thread = RandomThread()
thread.start()
#socketio.on('disconnect', namespace='/test')
def test_disconnect():
print('Client disconnected')
if __name__ == '__main__':
socketio.run(app)
I have a Python script which connects to a Websocket, receives data and prints this data.
import websocket
from bitmex_websocket import Instrument
from bitmex_websocket.constants import InstrumentChannels
from bitmex_websocket.constants import Channels
import json
websocket.enableTrace(True)
channels = [
InstrumentChannels.trade,
]
XBTUSD = Instrument(symbol='XBTUSD',
channels=channels)
XBTUSD.on('action', lambda msg: test(msg))
def test(msg):
parsed = json.loads(json.dumps(msg))
print(parsed)
XBTUSD.run_forever()
I now want to print this data on my webpage, i tried to "merge" these two scripts but apparently i can't, because to run the Websocket connector i have to run XBTUSD.run_forever(), which will start the process but it won't run the rest of the code, including the Flask part which generates the webpage, so only one at time can run.
Is there a way to make the Websocket connector communicate with the Flask/Socketio part so that the data from the Websocket connector is printed on the webpage?
I would like to stop my flask server as soon as an unhandled exception occurs.
Here is an example:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
1/0 # argh, exception
return 'Hello World!'
if __name__ == '__main__':
app.run(port=12345)
If you run this and go to localhost:12345, your browser tells you "internal server error" and the python console logs a DivisionByZero exception.
But the server app doesn't crash. Flask wraps your routes into its own error handling and it only prints the exception.
I would like to make the server stop as soon as a route produces an exception. But I didn't find this behaviour in the API. You can specify an errorhandler but that is only to give custom error messages to the client after your route failed.
Stopping Flask requires getting into Werkzeug internals. See http://flask.pocoo.org/snippets/67/
Extracted from a single-user app:
from flask import request
#app.route('/quit')
def shutdown():
...
shutdown_hook = request.environ.get('werkzeug.server.shutdown')
if shutdown_hook is not None:
shutdown_hook()
return Response("Bye", mimetype='text/plain')
The shutdown_hook bit is what you'd need in an exception handler.
from multiprocessing import Process
server = Process(target=app.run)
server.start()
# ...
server.terminate()
server.join()
or if Threaded to run Flask Web Server in background around other python code:
import threading
import ctypes
webserverurl = 127.0.0.1
webserverport = 8080
class thread_with_exception(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
self.interval = 1
self.daemon = True
def __del__(self):
print(f"Thread terminated");
def run(self):
# target function of the thread class
try:
while True:
print(f"{self.name} Waiting for Web")
app.run(host=webserverurl, port=webserverport)
finally:
print('ended')
def get_id(self):
# returns id of the respective thread
if hasattr(self, '_thread_id'):
return self._thread_id
for id, thread in threading._active.items():
if thread is self:
return id
def raise_exception(self):
thread_id = self.get_id()
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_id), ctypes.py_object(SystemExit))
print(f"{self.name} terminated")
if res > 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_id), 0)
print('Exception raise failure')
t1 = thread_with_exception('Web Server 1')
t1.start()
time.sleep(10)
t1.raise_exception()
# del t1
credit to Andrew Abrahamowicz here:
https://code.activestate.com/recipes/496960-thread2-killable-threads
ctypes.c_long( required for Linux else Windows only: https://stackoverflow.com/a/61638782/3426192
other ways to do this here: https://w3guides.com/tutorial/how-to-close-a-flask-web-server-with-python