33

I'm a little confused about how to do something that I thought would be quite simple. I have a simple app written using Flask. It looks something like this:

from flask import Flask

app = Flask(__name__)

def _run_on_start(a_string):
    print "doing something important with %s" % a_string

@app.route('/')
def root():
    return 'hello world'

if __name__ == "__main__":
    if len(sys.argv) < 2:
        raise Exception("Must provide domain for application execution.")
    else:
        DOM = sys.argv[1]
        _run_on_start("%s" % DOM)
        app.run(debug=True)

What I'm finding is that my terminal is outputting the print statements in _run_on_start but non of the other usual Flask app debug code. If I remove the call before app.run, the output is normal. Further I'm finding the output of _run_on_start to be repeated twice on startup, though I don't know if it's some weird output or the function is actually being called twice.

I'm assuming this is not the right way to add a function call before you call app.run. I looked in the Flask docs and found mentions of various decorators one can use, which allow you to execute a function before/after certain requests but I want to execute the call when the app server is run.

Further, I realise that if I call this module from another module, i.e., not when __name__ != "__main__" my I won't get my call to _run_on_start.

What's the right approach here? In both cases when I'm starting from the CL and from another module?

Edwardr
  • 2,906
  • 3
  • 27
  • 30
  • This will probably answer the question: http://stackoverflow.com/questions/27465533/run-code-after-flask-application-has-started?noredirect=1&lq=1 – Jeevan Gyawali Apr 10 '17 at 18:33

3 Answers3

49

Probably you were looking for Flask.before_first_request decorator, as in:

@app.before_first_request
def _run_on_start(a_string):
    print "doing something important with %s" % a_string
the-happy-hippo
  • 1,203
  • 1
  • 9
  • 13
  • 17
    is there a way to call a function before app getting first request ? i need to run a function right after nginx(for example) started ? – Sepehr Hamzehlooy Mar 09 '16 at 07:18
  • 12
    This will be called only after the first request is made. Thus its inappropriate in most cases were you want to initialize a lot of staff before starting making responses. – stelios Nov 10 '16 at 12:57
  • Suggest `a_string` be removed. The [doc](http://flask.pocoo.org/docs/api/#flask.Flask.before_first_request) says: "The function will be called without any arguments and its return value is ignored." – Bob Stein Jun 03 '19 at 11:29
  • @tktktk0711 I suggest you to create an app context and do you job there. – Sepehr Hamzehlooy Jul 16 '19 at 12:45
  • Hi @SepehrHamzelooy thanks for your answer. my question is here:https://stackoverflow.com/questions/56991587/how-to-run-my-function-code-before-flask-application-has-started-in-the-server – tktktk0711 Jul 17 '19 at 03:09
16

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.

robots.jpg
  • 5,001
  • 1
  • 38
  • 41
1
from flask import Flask

def create_app():
    app = Flask(__name__)
    def run_on_start(*args, **argv):
        print "function before start"
    run_on_start()
    return app

app = create_app()

@app.route("/")
def hello():
    return "Hello World!"
Peretz30
  • 1,264
  • 1
  • 11
  • 15