Почему запуск сервера Flask dev выполняется дважды?
Я использую Flask для разработки веб-сайта, а во время разработки я запускаю колбу, используя следующий файл:
#!/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')
Когда я запускаю сервер или когда он автоматически перезапускается из-за того, что файлы были обновлены, он всегда показывает строку печати дважды:
################### Restarting @ 2014-08-26 10:51:49.167062 ###################
################### Restarting @ 2014-08-26 10:51:49.607096 ###################
Хотя это на самом деле не проблема (все остальное работает как положено), мне просто интересно, почему он так себя ведет? Есть идеи?
Ответы
Ответ 1
Reloader Werkzeug порождает дочерний процесс, так что он может перезапускать этот процесс каждый раз, когда ваш код изменяется. Werkzeug - это библиотека, которая снабжает Flask сервером разработки при вызове app.run()
.
Смотрите код функции restart_with_reloader()
; ваш сценарий запускается снова с subprocess.call()
.
Если вы установите use_reloader
на False
, вы увидите, что поведение исчезнет, но при этом вы также потеряете функцию перезагрузки:
app.run(port=4004, debug=config.DEBUG, host='0.0.0.0', use_reloader=False)
Вы также можете отключить перегрузчик при использовании команды flask run
:
FLASK_DEBUG=1 flask run --no-reload
Вы можете найти переменную среды WERKZEUG_RUN_MAIN
, если хотите определить, когда вы находитесь в процессе перезагрузки дочернего процесса:
import os
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
print '################### Restarting @ {} ###################'.format(
datetime.utcnow())
Однако, если вам нужно настроить глобальные переменные модуля, вам следует вместо этого использовать декоратор @app.before_first_request
для функции, и эта функция должна устанавливать такие глобальные переменные. Он будет вызываться один раз после каждой перезагрузки, когда поступит первый запрос:
@app.before_first_request
def before_first_request():
print '########### Restarted, first request @ {} ############'.format(
datetime.utcnow())
Учтите, что если вы запустите это на полномасштабном сервере WSGI, который использует разветвление или новые подпроцессы для обработки запросов, то обработчики before_first_request
могут вызываться для каждого нового подпроцесса.
Ответ 2
Если вы используете современную команду flask run
, ни одна из опций app.run
не используется. Чтобы полностью отключить перезагрузку, пройдите --no-reload
:
FLASK_DEBUG=1 flask run --no-reload
Кроме того, __name__ == '__main__'
никогда не будет истинным, потому что приложение не выполняется напрямую. Используйте те же идеи из Martijn answer, за исключением блока __main__
.
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
Ответ 3
У меня была такая же проблема, и я решил ее, установив app.debug
в False
. Установка его на True
вызывала мой вызов __name__ == "__main__"
дважды.
(Я бы разместил это как комментарий, но мне не хватило репутации. Добавлено как ответ в надежде, что это поможет кому-то другому)
Ответ 4
Я была такая же проблема. Я решил это, изменив мой main и вставив в него use_reloader = False. Если какое-либо тело ищет здесь обходной путь для этой проблемы, то приведенный ниже код поможет вам начать работу, однако функциональность изменений в коде, автоматически обнаруживаемых и перезапускающих приложение, не будет работать. Вам придется вручную останавливать и перезапускать ваше приложение после каждого редактирования в коде.
if __name__ == '__main__':
app.run(debug=True,use_reloader=False)
Ответ 5
Одной из возможных причин, по которой приложение Flask запускается дважды, является настройка параметра WEB_CONCURRENCY
в Heroku. Чтобы установить в один, вы можете написать в консоли
heroku config:set WEB_CONCURRENCY=1