Pregunta

Actualmente estoy jugando con el frasco y no puedo averiguar cómo funciona el mecanismo de depuración está trabajando. Para ser más precisos al guardar el archivo de pitón con mi solicitud no tenga que reiniciar el servidor, se carga automáticamente cuando hago una petición. Así que mi pregunta es ¿cómo sabe el programa que se ejecuta fue cambiado y responder a que los cambios?

¿Fue útil?

Solución

Frasco está utilizando la función de Werkzug subyacente run_with_reloader (que se encuentra en serving.py) ... lo cual es en sí mismo utilizando la función restart_with_reloader y reloader_loop creado anteriormente en el mismo archivo.

desova run_with_reloader otro proceso pitón (correr Werkzug de nuevo con todos los mismos argumentos que se pasan a la primera de ellas) y este nuevo proceso utiliza el módulo thread a generar un nuevo subproceso o subproceso que ejecuta la función de servidor. A continuación, ejecuta el reloader_loop y espera.

reloader_loop simplemente recorre todos los módulos que se han importado y obtiene sus fechas de última modificación. Luego, a intervalos especificados (que por defecto es 1 s) que comprueba todos los archivos de nuevo para ver si han sido modificados. Si es así, el actualmente en ejecución ( esclavo ) termina el proceso Werkzug (termina) con el código de salida 3. Una vez que sale, el hilo o subproceso que comenzó (que en realidad está haciendo el trabajo) se termina también. Los principal cheques proceso para ver si el código de salida fue de 3. Si lo fuera, se genera un nuevo esclavo subproceso, tal como lo hizo antes. De lo contrario, se sale con el mismo código de salida.

Este es el código de referencia:

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

Otros consejos

El built-in reload() función puede hacer esto para usted. Es probable que esta función está detrás de lo que hace a Frasco código de recarga (después de darse cuenta de que ha cambiado en el disco de alguna manera).

La pregunta ¿Cómo se descarga (recarga) un módulo de Python? tiene más información al respecto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top