Run code after flask application has started

后端 未结 6 915
渐次进展
渐次进展 2020-12-09 14:54

My goal is to get arbitrary code to run after my Flask application is started. Here is what I\'ve got:

def run():
    from webapp import app
    app.run(debu         


        
相关标签:
6条回答
  • 2020-12-09 15:02

    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.

    0 讨论(0)
  • 2020-12-09 15:05

    Use Flask-Script to run your app, then overwrite the runserver class/method like this

    # manage.py
    
    from flask.ext.script import Manager
    
    from myapp import app
    
    manager = Manager(app)
    
    def crazy_call():
        print("crazy_call")
    
    @manager.command
    def runserver():
        app.run()
        crazy_call()
    
    if __name__ == "__main__":
        manager.run()
    
    0 讨论(0)
  • 2020-12-09 15:06

    If you want to run a bunch of command (as a regular Py app) after flask run, use a multi processing library (for example multiprocessing), In this solution you can have an API/Web application beside of a system program.

    import flask
    from flask import request, jsonify,make_response
    import time
    import multiprocessing
    
    app = flask.Flask('__name__')
    
    def API(Conf):
       print('In API selction')
       app.run(host='0.0.0.0', port=1337,)
    if __name__ == "__main__":
       config = {"Something":"SomethingElese"}
       p = multiprocessing.Process(target=API, args=(Conf,))
       p.start()
       #time.sleep(3)
       print('After Flask run')
    

    Note: above code just a sample/idea. Maybe have some error. (But I used this solution in production area and it's fine.)

    P.S. : (in my perspective) the problem of this solution: more difficulty in debugging section.

    0 讨论(0)
  • 2020-12-09 15:16

    I just did (in a main.py executed with python main.py):

    with app.app_context():
        from module import some_code
        some_code()
    
    def run():
        from webapp import app
        app.run(debug=True, use_reloader=False)
    

    This worked for me without the more comprehensive answers offered above. In my case some_code() is initializing a cache via flask_caching.Cache.

    But it probably depends on what exactly some_code is doing...

    0 讨论(0)
  • 2020-12-09 15:19

    I don't really like any of the methods mentioned above, for the fact that you don't need Flask-Script to do this, and not all projects are going to use Flask-Script already.

    The easiest method, would be to build your own Flask sub-class. Where you construct your app with Flask(__name__), you would simply add your own class and use it instead.

    def do_something():
      print('MyFlaskApp is starting up!')
    
    
    class MyFlaskApp(Flask):
      def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
        if not self.debug or os.getenv('WERKZEUG_RUN_MAIN') == 'true':
          with self.app_context():
            do_something()
        super(MyFlaskApp, self).run(host=host, port=port, debug=debug, load_dotenv=load_dotenv, **options)
    
    
    app = MyFlaskApp(__name__)
    app.run()
    

    Of course, this doesn't run after it starts, but right before run() is finally called. With app context, you should be able to do anything you may need to do with the database or anything else requiring app context. This should work with any server (uwsgi, gunicorn, etc.) as well.

    If you need the do_something() to be non-blocking, you can simply thread it with threading.Thread(target=do_something).start() instead.

    The conditional statement is to prevent the double call when using debug mode/reloader.

    0 讨论(0)
  • 2020-12-09 15:19

    I encountered this same issue in a flask app of mine. I wanted to start a scheduler at app startup, which would kick off some jobs at regular intervals. Since I deploy my apps inside docker containers, what I ended up doing is adding an "health check" endpoint which just returns a 200, and in my dockerfile configured that endpoint:

    HEALTHCHECK CMD curl --fail http://localhost:8080/alive || exit 1

    The default behavior is to execute that command every 30s, and the first run conveniently kicks off my init() method. https://docs.docker.com/engine/reference/builder/#healthcheck

    0 讨论(0)
提交回复
热议问题