Starting thread while running flask with debug - python

When I try to start a thread in the same process as a flask app is running, two threads are started. So "once" will be printed twice.
from threading import Timer
from flask import Flask
app = Flask(__name__)
app.config.update(dict(
DEBUG = True
))
def once():
print("once")
t = Timer(1, once, ())
t.start()
app.run()
This only happens when DEBUG is true.
Anyone have any idea how to prevent this from happening when debugging?

Werkzeug's reloading support has to fork to be able to reload the module correctly. As such your module is imported twice at least; more if you altered the module and it is reloaded.
You can switch this off the reloader with use_reloader=False:
app.run(use_reloader=False)
or you can start your thread in a #app.before_first_request decorated function:
t = Timer(1, once, ())
#app.before_first_request
def start_thread():
t.start()
The start_thread function is now only executed when the first request comes in, not when importing.

Related

Python threading in flask webapp

I've been trying threads recently in my webapp, and I've come across an issue that I cannot seem to solve.
The issue is that I have an index page, and every time the user enters that page, a new thread is being started which checks for changes in my database in a while loop, although I only want one thread to be on at that moment. Is there a way to "kill" a thread when the index page is accessed the second time and then start a new one?
I did try to use is_alive() to check if a thread is already running, but had no success since all the time they're different.
Code example below:
#app.route("/")
def index():
#copy_current_request_context
def check_for_updates():
while True:
...... # Query for information
if something_changed:
socketio.emit('new_notifications', {'data': new_data})
if index_opened_again:
break
sleep(5)
index_thread = threading.Thread(target=check_for_updates, daemon=True)
index_thread.start()
return render_template("index.html")
I user the below code to kill threads when I am existing a server ,
My suggestion is to kill all active threadss before opening a new one
for id, thread in threading._active.items():
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, ctypes.py_object(SystemExit))
In my example I use a global variable in combination with a lock. It's certainly not optimal, but you can check if a thread is already running.
If you're using flask-socketio anyway, I recommend you take a look at start_background_task. The functionality is compatible with that of a standard thread.
from threading import Lock
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.secret_key = 'your secret here'
sio = SocketIO(app)
thread = None
thread_lock = Lock()
def background_task():
while True:
# ...
sleep(5)
#app.route('/')
def index():
global thread
with thread_lock:
if thread is None:
thread = sio.start_background_task(background_task)
return render_template('index.html')
if __name__ == '__main__':
sio.run(app)

flask background task using `threading.Thread` is blocking main thread

I have a long-running background task that spins the flask app again and to do some auditing in the background. The front end is a web application and uses socketio to communicate with the backend main flask app to handle multiple async behaviors.
I make sure to only fire the background task when the main thread is created and I do eventlet.monkey_patch() only at the very beginning of the script.
if the background thread has a lot of stuff to audit, it blocks the main thread, the more stuff in memory, the longer it blocks the main thread. The audit is not CPU intensive at all, it's just some db inserts and logging.
The items that need to be audited are added to an object in memory from the main thread and are passed by reference to the child thread. (Like a in memory queue)
If I don't monkey patch eventlet, then everything works fine but then flask's auto reload won't work, and I need it for development.
I run the app like socketio.run(app) in dev
Behavior persists when using gunicorn/eventlet
When the background task is sleeping sleep(2), there's no block happening.
import eventlet
eventlet.monkey_patch()
# ... rest of code is a basic flask app create_app factory that at some # point starts the new thread if it's the main thread
# the async code that runs is the following
class AsyncAuditor(threading.Thread):
def __init__(self, tasks: list, stop: threading.Event):
super().__init__()
self.tasks = tasks
self.stop_event = stop
def run(self):
from app import init_app
from dal import db
app = init_app(mode='sys')
app.logger.info('starting async audit thread')
with app.app_context():
try:
while not self.stop_event.is_set():
if len(self.tasks) > 0:
task: dict
for task in self.tasks:
app.logger.debug(threading.current_thread().name + ' new audit record')
task.payload = encryptor.encrypt(task.payload)
task.ip = struct.unpack("!I", socket.inet_aton(task.ip))[0]
db.session.add(task)
self.tasks.clear()
db.session.commit()
sleep(2)
app.logger.info('exiting async audit thread')
except BaseException as e:
app.logger.exception('Exception')
# there's some code that tries to gracefully exit if app needs to exit
stop_event = threading.Event()
async_task = AsyncAuditor(API.audit_tasks, stop_event)
async_task.start()
def exit_async_thread():
stop_event.set()
async_task.join()
atexit.register(exit_async_thread)
I expect that while the child thread is working, the main thread would not be blocked by any db operations, in fact, like I mentioned before, if I don't monkey patch eventlet, then everything works fine in the main thread and the child one as well. Instead, I'm getting 9 and even 30 seconds delays when hitting an endpoint in the flask application while the background task is working.

Threading not working in flask

I'm trying to use threading in my flask app, like:
#app.route('/index')
def index():
t = threading.Thread(do_sth_else())
t.start()
print('ready to response')
return render_template('index.html')
def do_sth_else():
time.sleep(5)
print('sth else done')
When calling 127.0.0.1:5000/index in the browser, the result in the server console is not what I expected:
sth else done
ready to response
I want the do_sth_else() function to run in some other thread, while the index() function go on returning the response right away, which means I should see the above result in defferent order.
So I want to know:
Why the index() function kept waiting until do_sth_else() is finished
How do I get the app working as I wanted
Thanks!
t = threading.Thread(do_sth_else()) calls do_sth_else() and pass it's result to Thread.
You should use it like t = threading.Thread(do_sth_else).
This example working as you want (tested on Python 3.4.3)
from time import sleep
from concurrent.futures import ThreadPoolExecutor
# DOCS https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor
executor = ThreadPoolExecutor(2)
#app.route('/index')
def index():
executor.submit(do_sth_else)
print('ready to response')
return render_template('index.html')
def do_sth_else():
print("Task started!")
sleep(10)
print("Task is done!")
For actual parallelization in Python, you should use the multiprocessing module to fork multiple processes that execute in parallel.
Python threads provide interleaving, but are in fact executed serially, not in parallel.
This applies to CPython due to the existence of global interpreter lock, otherwise true concurrency is bound to number of cpu's you have

flask\werkzeug: intercept a worker termination

Is there any way to execute some code just before a worker is turned off?
I'm not too confident on execution model of flask\werkzeug, the situation is this:
During the creation of flask application i start a deamon thread to do some external stuff (waiting on a queue essentially); i've setup this thread as demon because i don't want it to prevent the shut down of the worker running the flask application when it's needed.
there is my problem: i need to execute some clean up code just before the thread it's been killed by the worker, and my solution is to do those operations on a termination event (if any) of the worker
With python you can use the uwsgi.atexit hook. The function callback will be executed before exit.
import uwsgi, os
from flask import Flask
app = Flask('demo')
#app.route('/')
def index():
return "Hello World"
def callback():
print "Worker %i exinting" % os.getpid()
uwsgi.atexit = callback

Run a function once on bottle.py startup

I have a bottle app that I eventually wan't to deploy on apache (just fyi in case that's important).
Now I need to run a function once after the bottle app is started. I can't just put it into a routed function because it has to run even if no user has accessed the site yet.
Any best pratice to do this ?
The function starts a APScheduler Instance and adds a jobstore to it.
Here's what I do.
def initialize():
//init whatever you need.
if __name__ == '__main__':
initialize()
#bottle.run(port='8080', yatta yatta)
Honestly your problem is simply a sync vs async issue. Use gevent to easily convert to microthreads, and then launch each separately. You can even add a delay either in your function or before with gevent.sleep if you want to wait for the web server to finish launching.
import gevent
from gevent import monkey, signal, spawn, joinall
monkey.patch_all()
from gevent.pywsgi import WSGIServer
from bottle import Bottle, get, post, request, response, template, redirect, hook, abort
import bottle
#get('/')
def mainindex():
return "Hello World"
def apScheduler():
print "AFTER SERVER START"
if __name__ == "__main__":
botapp = bottle.app()
server = WSGIServer(("0.0.0.0", 80), botapp)
threads = []
threads.append(spawn(server.serve_forever))
threads.append(spawn(apScheduler))
joinall(threads)
Create an APScheduler class.
Look at examples of object use and creation in this same site bacause it's too general to give an especific example to copy.
I don't know if this helps.
class Shed(object):
def __init__(self): # this to start it
# instruccions here
def Newshed(self, data):
# Call from bottle
# more methods ...
...
# init
aps = Shed() # this activates Shed.__init__()
...
# in the #router
x = aps.Newshed(data) # or whatever
Anyway I'm still learning this stuff and it's just an idea.
import threading
import bottle
def init_app():
def my_function_on_startup():
# some code here
pass
app = bottle.app()
t = threading.Thread(target=my_function_on_startup)
t.daemon = True
t.start()
return app
app = init_app()
#app.route("/")
def hello():
return "App is running"
if __name__ == "__main__":
bottle.run(app, host='localhost', port=8080, debug=True)

Categories