How to set up autoreload with Flask+uWSGI?

后端 未结 7 1776
清酒与你
清酒与你 2020-12-13 00:41

I am looking for something like uWSGI + django autoreload mode for Flask.

相关标签:
7条回答
  • 2020-12-13 00:52

    I am running uwsgi version 1.9.5 and the option

    uwsgi --py-autoreload 1
    

    works great

    0 讨论(0)
  • 2020-12-13 00:58

    You could try using supervisord as a manager for your Uwsgi app. It also has a watch function that auto-reloads a process when a file or folder has been "touched"/modified.

    You will find a nice tutorial here: Flask+NginX+Uwsgi+Supervisord

    0 讨论(0)
  • 2020-12-13 00:59

    I am afraid that Flask is really too bare bones to have an implementation like this bundled by default.

    Dynamically reloading code in production is generally a bad thing, but if you are concerned about a dev environment, take a look at this bash shell script http://aplawrence.com/Unixart/watchdir.html

    Just change the sleep interval to whatever suits your needs and substitute the echo command with whatever you use to reload uwsgi. I run uwsgi un master mode and just send a killall uwsgi command.

    0 讨论(0)
  • 2020-12-13 01:12

    The auto-reloading functionality of development-mode Flask is actually provided by the underlying Werkzeug library. The relevant code is in werkzeug/serving.py -- it's worth taking a look at. But basically, the main application spawns the WSGI server as a subprocess that stats every active .py file once per second, looking for changes. If it sees any, the subprocess exits, and the parent process starts it back up again -- in effect reloading the chages.

    There's no reason you couldn't implement a similar technique at the layer of uWSGI. If you don't want to use a stat loop, you can try using underlying OS file-watch commands. Apparently (according to Werkzeug's code), pyinotify is buggy, but perhaps Watchdog works? Try a few things out and see what happens.

    Edit:

    In response to the comment, I think this would be pretty easy to reimplement. Building on the example provided from your link, along with the code from werkzeug/serving.py:

    """ NOTE: _iter_module_files() and check_for_modifications() are both
        copied from Werkzeug code. Include appropriate attribution if
        actually used in a project. """
    import uwsgi
    from uwsgidecorators import timer
    
    import sys
    import os
    
    def _iter_module_files():
        for module in sys.modules.values():
            filename = getattr(module, '__file__', None)
            if filename:
                old = None
                while not os.path.isfile(filename):
                    old = filename
                    filename = os.path.dirname(filename)
                    if filename == old:
                        break
                else:
                    if filename[-4:] in ('.pyc', '.pyo'):
                        filename = filename[:-1]
                    yield filename
    
    @timer(3)
    def check_for_modifications():
        # Function-static variable... you could make this global, or whatever
        mtimes = check_for_modifications.mtimes
        for filename in _iter_module_files():
            try:
                mtime = os.stat(filename).st_mtime
            except OSError:
                continue
    
            old_time = mtimes.get(filename)
            if old_time is None:
                mtimes[filename] = mtime
                continue
            elif mtime > old_time:
                uwsgi.reload()
                return
    
    check_for_modifications.mtimes = {} # init static
    

    It's untested, but should work.

    0 讨论(0)
  • 2020-12-13 01:14

    If you're configuring uwsgi with command arguments, pass --py-autoreload=1:

    uwsgi --py-autoreload=1
    

    If you're using a .ini file to configure uwsgi and using uwsgi --ini, add the following to your .ini file:

    py-autoreload = 1
    
    0 讨论(0)
  • 2020-12-13 01:15
    import gevent.wsgi
    import werkzeug.serving
    
    @werkzeug.serving.run_with_reloader
    def runServer():
        gevent.wsgi.WSGIServer(('', 5000), app).serve_forever()
    

    (You can use an arbitrary WSGI server)

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