¿Por qué la ejecución del servidor de desarrollo Flask se ejecuta dos veces?

Resuelto kramer65 asked hace 10 años • 8 respuestas

Estoy usando Flask para desarrollar un sitio web y durante el desarrollo ejecuto flask usando el siguiente archivo:

#!/usr/bin/env python
from datetime import datetime
from app import app
import config

if __name__ == '__main__':
    print('################### Restarting @', datetime.utcnow(), '###################')
    app.run(port=4004, debug=config.DEBUG, host='0.0.0.0')

Cuando inicio el servidor, o cuando se reinicia automáticamente porque los archivos se actualizaron, siempre muestra la línea de impresión dos veces:

################### Restarting @ 2014-08-26 10:51:49.167062 ###################
################### Restarting @ 2014-08-26 10:51:49.607096 ###################

Aunque realmente no es un problema (el resto funciona como se esperaba), simplemente me pregunto ¿por qué se comporta así? ¿Algunas ideas?

kramer65 avatar Aug 26 '14 17:08 kramer65
Aceptado

El recargador Werkzeug genera un proceso hijo para que pueda reiniciarlo cada vez que cambia su código. Werkzeug es la biblioteca que proporciona a Flask el servidor de desarrollo cuando llamas app.run().

Ver el restart_with_reloader()código de función ; su script se ejecuta nuevamente con subprocess.call().

Si lo configura, use_reloaderverá Falseque el comportamiento desaparece, pero también perderá la funcionalidad de recarga:

app.run(port=4004, debug=config.DEBUG, host='0.0.0.0', use_reloader=False)

flask runTambién puedes desactivar el recargador cuando usas el comando:

FLASK_DEBUG=1 flask run --no-reload

Puede utilizar la werkzeug.serving.is_running_from_reloaderfunción si desea detectar cuándo se encuentra en el proceso secundario de recarga:

from werkzeug.serving import is_running_from_reloader

if is_running_from_reloader():
    print(f"################### Restarting @ {datetime.utcnow()} ###################")

Sin embargo, si necesita configurar globales de módulo, entonces debería usar el @app.before_first_requestdecorador en una función y hacer que esa función configure dichas globales. Se llamará solo una vez después de cada recarga cuando llegue la primera solicitud:

@app.before_first_request
def before_first_request():
    print(f"########### Restarted, first request @ {datetime.utcnow()} ############")

Tenga en cuenta que si ejecuta esto en un servidor WSGI a gran escala que utiliza bifurcaciones o nuevos subprocesos para manejar solicitudes, se puedenbefore_first_request invocar controladores para cada nuevo subproceso.

Martijn Pieters avatar Aug 26 '2014 11:08 Martijn Pieters

Si está utilizando el flask runcomando moderno, no app.runse utiliza ninguna de las opciones. Para desactivar el recargador por completo, pase --no-reload:

FLASK_DEBUG=1 flask run --no-reload

Además, __name__ == '__main__'nunca será cierto porque la aplicación no se ejecuta directamente. Utilice las mismas ideas de la respuesta de Martijn , excepto sin el __main__bloque.

if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
    # do something only once, before the reloader

if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
    # do something each reload
davidism avatar Nov 12 '2017 14:11 davidism

Tuve el mismo problema y lo resolví configurándolo app.debugen False. Configurarlo en Trueestaba causando que me __name__ == "__main__"llamaran dos veces.

Carvell Wakeman avatar Dec 14 '2016 18:12 Carvell Wakeman

A partir de Flask 0.11, se recomienda ejecutar la aplicación en flask runlugar de python application.py. Usar este último podría resultar en ejecutar su código dos veces.

Como se indica aquí :

... a partir del Flask 0.11 se recomienda el método del matraz. La razón de esto es que debido a cómo funciona el mecanismo de recarga, hay algunos efectos secundarios extraños (como ejecutar cierto código dos veces...)

salsa_man avatar Dec 19 '2019 12:12 salsa_man