I\'m busy writing a small game server to try out flask. The game exposes an API via REST to users. It\'s easy for users to perform actions and query data, however I\'d like to service the \"game world\" outside the app.run() loop to update game entities, etc. Given that Flask is so cleanly implemented, I\'d like to see if there\'s a Flask way to do this.
问题:
回答1:
Your additional threads must be initiated from the same app that is called by the WSGI server.
The example below creates a background thread that executes every 5 seconds and manipulates data structures that are also available to Flask routed functions.
import threading
import atexit
from flask import Flask
POOL_TIME = 5 #Seconds
# variables that are accessible from anywhere
commonDataStruct = {}
# lock to control access to variable
dataLock = threading.Lock()
# thread handler
yourThread = threading.Thread()
def create_app():
app = Flask(__name__)
def interrupt():
global yourThread
yourThread.cancel()
def doStuff():
global commonDataStruct
global yourThread
with dataLock:
# Do your stuff with commonDataStruct Here
# Set the next thread to happen
yourThread = threading.Timer(POOL_TIME, doStuff, ())
yourThread.start()
def doStuffStart():
# Do initialisation stuff here
global yourThread
# Create your thread
yourThread = threading.Timer(POOL_TIME, doStuff, ())
yourThread.start()
# Initiate
doStuffStart()
# When you kill Flask (SIGTERM), clear the trigger for the next thread
atexit.register(interrupt)
return app
app = create_app()
Call it from Gunicorn with something like this:
gunicorn -b 0.0.0.0:5000 --log-config log.conf --pid=app.pid myfile:app
回答2:
It looks like there\'s a hackish way to do it, but I don\'t think this is technically supported.
I also found this answer, which talks about using flask-celery for this.
回答3:
In addition to using pure threads or the Celery queue (note that flask-celery is no longer required), you could also have a look at flask-apscheduler:
https://github.com/viniciuschiele/flask-apscheduler
A simple example copied from https://github.com/viniciuschiele/flask-apscheduler/blob/master/examples/jobs.py:
from flask import Flask
from flask_apscheduler import APScheduler
class Config(object):
JOBS = [
{
\'id\': \'job1\',
\'func\': \'jobs:job1\',
\'args\': (1, 2),
\'trigger\': \'interval\',
\'seconds\': 10
}
]
SCHEDULER_API_ENABLED = True
def job1(a, b):
print(str(a) + \' \' + str(b))
if __name__ == \'__main__\':
app = Flask(__name__)
app.config.from_object(Config())
scheduler = APScheduler()
# it is also possible to enable the API directly
# scheduler.api_enabled = True
scheduler.init_app(app)
scheduler.start()
app.run()
回答4:
You can take a look at RQ.
Also check out Miguel Greenberg\'s awesome tutorial on background jobs using RQ and Flask.