Frage

Ich spiele zur Zeit mit Flasche und ich kann nicht herausfinden, wie der Debug-Mechanismus funktioniert. Um genauer zu sein, wenn ich die Python-Datei speichern mit meiner Anwendung Ich brauche nicht den Server neu starten, wird es automatisch geladen werden, wenn ich einen Antrag stellen. Also meine Frage ist, wie weiß das laufende Programm wurde zu, dass Änderungen geändert und darauf zu reagieren?

War es hilfreich?

Lösung

Kolben werden mit Werkzug zugrunde liegende run_with_reloader Funktion (in serving.py gefunden) ... die sich die restart_with_reloader und reloader_loop Funktion früher in der gleichen Datei erstellt wird.

run_with_reloader Spawns eine andere Python-Prozess (Lauf Werkzug wieder mit allen den gleichen Argumenten, dass Sie zum ersten bestanden) und dieser neuen Prozesse verwendet das thread Modul einen neuen Thread oder subprocess zum Laichen, die Ihre Server-Funktion ausgeführt wird. Es läuft dann die reloader_loop und wartet.

reloader_loop einfach eine Schleife durch alle Module, die importiert wurden und bekommt ihre letzten geänderten Daten. Dann in bestimmten Abständen (die standardmäßig auf 1 s) er alle die Dateien erneut überprüft, ob sie geändert worden sind. Wenn sie haben, ( Sklave ) die aktuell laufenden Werkzug Prozess beendet (beendet) mit einem Exit-Code 3. Sobald verlässt es das Gewinde oder subprocess es gestartet (die eigentlich die Arbeit tun) beendet auch. Der Master Prozess überprüft, ob der Exit-Code 3 war Wenn es ist, es laicht eine neue Sklave subprocess, so wie zuvor. Ansonsten ist es verläßt mit dem gleichen Exit-Code.

Hier ist der Code als Referenz:

def reloader_loop(extra_files=None, interval=1):
    """When this function is run from the main thread, it will force other
    threads to exit when any modules currently loaded change.

    Copyright notice.  This function is based on the autoreload.py from
    the CherryPy trac which originated from WSGIKit which is now dead.

    :param extra_files: a list of additional files it should watch.
    """
    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

    mtimes = {}
    while 1:
        for filename in chain(iter_module_files(), extra_files or ()):
            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:
                _log('info', ' * Detected change in %r, reloading' % filename)
                sys.exit(3)
        time.sleep(interval)


def restart_with_reloader():
    """Spawn a new Python interpreter with the same arguments as this one,
    but running the reloader thread.
    """
    while 1:
        _log('info', ' * Restarting with reloader...')
        args = [sys.executable] + sys.argv
        new_environ = os.environ.copy()
        new_environ['WERKZEUG_RUN_MAIN'] = 'true'

        # a weird bug on windows. sometimes unicode strings end up in the
        # environment and subprocess.call does not like this, encode them
        # to latin1 and continue.
        if os.name == 'nt':
            for key, value in new_environ.iteritems():
                if isinstance(value, unicode):
                    new_environ[key] = value.encode('iso-8859-1')

        exit_code = subprocess.call(args, env=new_environ)
        if exit_code != 3:
            return exit_code


def run_with_reloader(main_func, extra_files=None, interval=1):
    """Run the given function in an independent python interpreter."""
    if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
        thread.start_new_thread(main_func, ())
        try:
            reloader_loop(extra_files, interval)
        except KeyboardInterrupt:
            return
    try:
        sys.exit(restart_with_reloader())
    except KeyboardInterrupt:
        pass

Andere Tipps

Der eingebaute in reload() Funktion kann dies für Sie tun. Es ist wahrscheinlich, dass diese Funktion ist hinter dem, was Flask antut Reload-Code (nach zu bemerken, dass es auf der Festplatte in irgendeiner Weise geändert hat).

Die Frage Wie entladen ich (Reload) ein Python-Modul? hat weitere Informationen zu diesem Thema.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top