Run Code After Flask Application Has Started

Run code after flask application has started

If you need to execute some code after your flask application is started but strictly before the first request, not even be triggered by the execution of the first request as @app.before_first_request can handle, you should use Flask_Script, as CESCO said, but you could subclass the class Server and overwrite the __ call __ method, instead of overwriting the runserver command with @manager.command:

from flask import Flask
from flask_script import Manager, Server

def custom_call():
#Your code
pass

class CustomServer(Server):
def __call__(self, app, *args, **kwargs):
custom_call()
#Hint: Here you could manipulate app
return Server.__call__(self, app, *args, **kwargs)

app = Flask(__name__)
manager = Manager(app)

# Remeber to add the command to your Manager instance
manager.add_command('runserver', CustomServer())

if __name__ == "__main__":
manager.run()

This way you don't override default options of runserver command.

How to excecute code after Flask `app.run()` statement (run a Flask app and a function in parallel, execute code while Flask server is running)

You can do what you want by using multithreading:

from flask import Flask
import threading
import time

app = Flask(__name__)

@app.route("/")
def hello_world():
return "Hello, World!"

def run_app():
app.run(debug=False, threaded=True)

def while_function():
i = 0
while i < 20:
time.sleep(1)
print(i)
i += 1

if __name__ == "__main__":
first_thread = threading.Thread(target=run_app)
second_thread = threading.Thread(target=while_function)
first_thread.start()
second_thread.start()

Output:

 * Serving Flask app "app"
* Environment: production
* Debug mode: off
* Running on [...] (Press CTRL+C to quit)
0
1
2
3
4
5
6
7
8
[...]

The idea is simple:

  • create 2 functions, one to run the app and an other to execute the wile loop,
  • and then execute each function in a seperate thread, making them run in parallel

You can do this with multiprocessing instead of multithreading too:

The (main) differences here is that the functions will run on different CPUs and in memory spaces.

from flask import Flask
from multiprocessing import Process
import time

# Helper function to easly parallelize multiple functions
def parallelize_functions(*functions):
processes = []
for function in functions:
p = Process(target=function)
p.start()
processes.append(p)
for p in processes:
p.join()

# The function that will run in parallel with the Flask app
def while_function():
i = 0
while i < 20:
time.sleep(1)
print(i)
i += 1

app = Flask(__name__)

@app.route("/")
def hello_world():
return "Hello, World!"

def run_app():
app.run(debug=False)

if __name__ == '__main__':
parallelize_functions(while_function, run_app)

If you want to use before_first_request proposed by @Triet Doan: you will have to pass the while function as an argument of before_first_request like this:

from flask import Flask
import time

app = Flask(__name__)

def while_function(arg):
i = 0
while i < 5:
time.sleep(1)
print(i)
i += 1

@app.before_first_request(while_function)
@app.route("/")
def index():
print("index is running!")
return "Hello world"

if __name__ == "__main__":
app.run()

In this setup, the while function will be executed, and, when it will be finished, your app will run, but I don't think that was what you were asking for?

What's the right approach for calling functions after a flask app is run?

The duplicate output from your function can be explained by the reloader. The first thing it does is start the main function in a new thread so it can monitor the source files and restart the thread when they change. Disable this with the use_reloader=False option.

If you want to be able to run your function when starting the server from a different module, wrap it in a function, and call that function from the other module:

def run_server(dom):
_run_on_start("%s" % dom)
app.run(debug=True, use_reloader=False)

if __name__ == '__main__':
if len(sys.argv) < 2:
raise Exception("Must provide domain for application execution.")
else:
DOM = sys.argv[1]
run_server(DOM)

The "right approach" depends on what you're actually trying to accomplish here. The built-in server is meant for running your application in a local testing environment before deploying it to a production server, so the problem of starting it from a different module doesn't make much sense on its own.

Run code after Flask server starts

Try to run the flask in a thread.

threading.Thread(target=app.run, args=(config.server_address, config.server_port)).start()

Flask run script after start

Put your code here:-

 if __name__ == "__main__":
#write your code here to execute first when the app run

Start function on run with Flask

You can use webbrowser to automatically open http://localhost:5000 in a web browser when running your flask app:

import webbrowser
...

if __name__ == '__main__':
webbrowser.open('http://localhost:5000')
app.run()

Run flask application with uWSGI

Your code under if __name__ == "__main__": is not executed because uwsgi does not run your script like python app.py. Instead it imports the module specified in wsgi-file and looks for an object specified as callable (app in our case). You can test it by using the following script:

from flask import Flask

app = Flask(__name__)

print(__name__)
if __name__ == '__main__':
app.run()

If you run it with python ./flask_app.py then the output will be

$ python ./flask_app.py
__main__
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

(notice __main__ - it means we're running the script). However if you run it with uwsgi the __name__ will be app (it will be the name of your file, so app in my case):

$ uwsgi --http 127.0.0.1:5000 --module app:app 
...
*** Operational MODE: single process ***
app
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x7fb2d0c067b0 pid: 46794 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 46794, cores: 1)

Similar output will be if you run your app with FLASK_APP=app flask run - it does not execute script, it just imports it and uses app object from it.

So, in order to initialize database you should either move your db initialization out of if __name__ == "__main__":

from flask import Flask

app = Flask(__name__)

class DB:
def init(self):
self.data = 'Hello, World'

db = DB()

@app.route("/")
def hello_world():
return db.data

db.init()

if __name__ == '__main__':
app.run()

Or add a before_first_request handler:

# replace db.init() with 
@app.before_first_request
def init_db():
db.init()

Notice the difference between them - if you put db.init() as a top-level statement it will be executed once you load app.py. If you register a before_first_request callback it will be executed once first request arrives to your application. Pick the one that works best for you.



Related Topics



Leave a reply



Submit