There are many ways to automatically reload code when developing and debugging WSGi applications. For example, if you are using Werkzeug, just pass the use_reloader argument:

run_sumple('127.0.0.1'.5000, app, use_reloader=True)
Copy the code

For Flask, werkzeug is actually used internally, so you need to set debug = true:

app.run(debug=True)
Copy the code

Django automatically reloads any code you change:

python manage.py runserver
Copy the code

All of these examples are useful for local development, but are not recommended for use in real production.

As a learning experience, how does Python make code reload automatically?

uWSGI

If you’re using UWSGi and Django, you can actually check out django’s auto-reload mechanism directly by jumping to the code:

import uwsgi
from uwsgidecorators import timer
from django.utils import autoreload

@timer(3)
def change_code_gracefull_reload(sig):
    if autoreload.code_changed():
        uwsgi.reload()
Copy the code

As you can see, Django uses a timer that continuously monitors code changes to start reloading functions.

If you use another framework, or none at all, you may need to implement code change monitoring yourself in your application. Here is a nice example code, borrowed and modified from Cherrypy:

import os, sys

_mtimes = {}
_win = (sys.platform == "win32")

_error_files = []

def code_changed(a):
    filenames = []
    for m in sys.modules.values():
        try:
            filenames.append(m.__file__)
        except AttributeError:
            pass
    for filename in filenames + _error_files:
        if not filename:
            continue
        if filename.endswith(".pyc") or filename.endswith(".pyo"):
            filename = filename[:- 1]
        if filename.endswith("$py.class"):
            filename = filename[:9 -] + ".py"
        if not os.path.exists(filename):
            continue # File might be in an egg, so it can't be reloaded.
        stat = os.stat(filename)
        mtime = stat.st_mtime
        if _win:
            mtime -= stat.st_ctime
        if filename not in _mtimes:
            _mtimes[filename] = mtime
            continue
        ifmtime ! = _mtimes[filename]: _mtimes.clear()try:
                del _error_files[_error_files.index(filename)]
            except ValueError:
                pass
            return True
    return False
Copy the code

You can save the above content in autoreload. Py in your project, and then we can call it like this (similar to the Django example) :

import uwsgi
from uwsgidecorators import timer
import autoreload

@timer(3)
def change_code_gracefull_reload(sig):
    if autoreload.code_changed():
        uwsgi.reload()
Copy the code

gunicorn

For Gunicorn, we need to write a script hook to the Gunicorn configuration:

import threading
import time
try:
    from django.utils import autoreload
except ImportError:
    import autoreload

def reloader(server):
    while True:
        if autoreload.code_changed():
            server.reload()
        time.sleep(3)

def when_ready(server):
    t = threading.Thread(target=reloader, args=(server, ))
    t.daemon = True
    t.start()
Copy the code

You need to save the above code to a file, such as config.py, and pass it to Gunicorn as follows:

gunicorn -c config.py application
Copy the code

External solutions

You can also restart your system in ways other than the WSGi service system itself that you are using, by simply sending a signal telling the system to restart the code, such as using watchdog. Such as:

watchmedo shell-command --patterns="*.py" --recursive --command='kill -HUP `cat /tmp/gunicorn.pid`' /path/to/project/
Copy the code

Please reserve the following information for reprinting:

The original link: www.vimiix.com/post/2018/0…