Подтвердить что ты не робот

Почему запуск сервера 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 ###################

Хотя это на самом деле не проблема (все остальное работает как положено), мне просто интересно, почему он так себя ведет? Есть идеи?

4b9b3361

Ответ 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