Функция вызова сразу после запуска сервера разработки django. (Джанго/Питон)

Я пытаюсь вызвать функцию сразу после команды python manage.py runserver, это может быть простая печать. Я прочитал кое-что и нашел довольно интересные темы о def ready(self), такие как Overriding AppConfig.ready() или Выполнять код, когда Django запускается только ОДИН РАЗ? Я следую инструкциям, но для версия django 2.1.3 не работает. Одна готовая функция просто не вызывается, в другой раз я получаю кучу AppRegistryNotReady exceptions. Я думаю, что функция вызова после старта сервера — вещь вполне обычная. Это не должно доставлять столько хлопот, но все же я не нахожу подходящего решения

ОБНОВЛЕНИЕ

Я попробовал другое решение

Я создаю класс промежуточного программного обеспечения, подобный этому:

import time


class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        while True:
            print("true")
            time.sleep(5)

    def __call__(self, request):

        response = self.get_response(request)

        return response

Теперь я получаю правильный вывод, например:

Performing system checks...

System check identified no issues (0 silenced).
January 03, 2019 - 14:10:55
Django version 2.1.3, using settings 'CMS.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
true
true
true
true
true
true
true
.
.
.

НО нет соединениявведите здесь описание изображения


person KyluAce    schedule 02.01.2019    source источник
comment
Вы были довольно ясны, но я просто удостоверяюсь: вы хотите, чтобы вызов функции происходил, когда сервер готов получать запросы, а не сразу после того, как он запустит свой собственный вызов?   -  person Charles Landau    schedule 02.01.2019
comment
@CharlesLandau Да, когда сервер будет готов, я хочу вызвать функцию   -  person KyluAce    schedule 02.01.2019
comment
Вы должны понимать, что после запуска сервера это довольно неоднозначное определение. Если вы используете установку с несколькими процессами, что является наиболее распространенным случаем в рабочей среде, у вас будет один запуск сервера для каждого процесса. Если процессы управляются внешним сервером (что, опять же, является наиболее распространенным случаем), то фронт может запускать новые процессы django в любое время. И давайте не будем говорить о наличии двух или более передних серверов за балансировщиком нагрузки — какое здесь определение запуска сервера?   -  person bruno desthuilliers    schedule 02.01.2019
comment
@CharlesLandau Я обновил вопрос   -  person KyluAce    schedule 03.01.2019
comment
@brunodeshuilliers Я обновил вопрос   -  person KyluAce    schedule 03.01.2019
comment
@KyluAce, что вы ожидаете от этого бесконечного цикла? Конечно, ваш браузер истекает, промежуточное ПО навсегда блокирует весь серверный процесс. И мне действительно интересно, как вы надеетесь решить проблему с запуском сервера на самом деле. Как насчет того, чтобы объяснить точно что вы пытаетесь сделать И ПОЧЕМУ вместо этого? Я сильно подозреваю, что здесь проблема XY (en.wikipedia.org/wiki/XY_problem)   -  person bruno desthuilliers    schedule 03.01.2019
comment
@brunodesthuilliers, так что нет возможности вызывать все время работающий в фоновом режиме метод во время работы сервера (который начинается с сервера)? Когда я, например, запускаю эту же функцию, но позже с помощью просмотра (нажмите кнопку и функция запускается), все работает как шарм   -  person KyluAce    schedule 03.01.2019
comment
@KyluAce ПОЖАЛУЙСТА, объясните свою НАСТОЯЩУЮ проблему - ту, которую вы пытаетесь решить, вызывая функцию сразу после запуска сервера - вместо этого. На данный момент все это пустая трата времени.   -  person bruno desthuilliers    schedule 03.01.2019
comment
@brunodesthuilliers Во-первых, у меня есть функция, которая должна все время работать в фоновом режиме. Эта функция проверяет некоторые значения из базы данных и т. Д. Эта функция должна работать все время, я имею в виду, что мне не нужно посещать веб-сайт, чтобы что-то сделать. Поэтому, если мне не нужно посещать веб-сайт, эта функция должна вызываться как можно быстрее, поэтому она должна запускаться сразу после запуска команды python manage.py runserver x.x.x.x:yyyy. проще не напишешь   -  person KyluAce    schedule 03.01.2019
comment
Используйте для этого специальный процесс — он не имеет ничего общего с серверным процессом django. Распространенными решениями являются cronjobs и асинхронные очереди задач (например, сельдерей).   -  person bruno desthuilliers    schedule 03.01.2019
comment
Кроме того, поскольку вы упомянули runserver : вы знаете, что вы НЕ должны использовать сервер разработки в производстве, не так ли?   -  person bruno desthuilliers    schedule 03.01.2019
comment
@brunodesthuilliers Я знаю, что это другая тема, но, может быть, вы могли бы указать мне направление, что мне делать, если мне нужно создать производственную версию, но она должна быть размещена локально   -  person KyluAce    schedule 04.01.2019
comment
Что не так с доком? docs.djangoproject.com/en/2.1/howto/deployment   -  person bruno desthuilliers    schedule 04.01.2019
comment
stackoverflow.com/questions/6791911 /   -  person Josh    schedule 18.02.2019


Ответы (2)


Редактировать:

Я все еще не уверен, чего вы пытаетесь достичь, и есть некоторые важные проблемы, которые подчеркнули комментаторы. Во-первых, ошибка AppRegistryNotReady: Apps aren't loaded yet действительно расстраивает, я ценю это. Я не уверен, как вы организовали свой проект, поэтому не могу предоставить точное решение. Это может быть способ, которым вы организовали свои файлы и откуда вы импортируете класс AppConfig вашего приложения. Поместили ли вы его или какие-либо пользовательские функции или классы в уровень пакета вашего приложения __init__.py, чтобы вы могли импортировать оттуда? Если это так, это сбивает с толку Django, см. https://stackoverflow.com/a/34136825/2275482

Во-вторых:

Я пытаюсь вызвать функцию сразу после команды python manage.py runserver

Я думаю, что мы изо всех сил пытаемся понять, чего вы пытаетесь достичь, и не путаете ли вы, когда ваше приложение Django запускается с запуском сервера. Как отмечают комментаторы, веб-сервер полностью независим от Django; это отдельный процесс.

Даже тестовый сервер в комплекте с Django не зависит от вашего приложения Django. Это просто простой сервер разработки, помещенный туда для удобства, но он не требуется и не должен использоваться в производстве. Django построен в соответствии с PEP 333. Насколько я знаю, он будет работать с любым веб-сервером WSGI, совместимым с PEP 333, будь то Apache и mod_wsgi, gunicorn или uWSGI и т. д. и т. д. Если вы хотите, чтобы код выполнялся в отношении используемого вами сервера, вам нужно изучить этот документация по серверу.

manage.py вроде django-admin — это просто утилита, помогающая в разработке, см. https://docs.djangoproject.com/en/2.1/ref/django-admin/. Когда вы вызываете manage.py runserver, вы вызываете утилиту, которая загружает ваше приложение и настраивает тестовый сервер. Вы можете увидеть поток выполнения, какие утилиты он импортирует и так далее в самом файле. Этот поток выполнения отличается от того, что произошло бы при использовании рабочего сервера.

Рабочий сервер, насколько мне известно, загружает ваше приложение django из корневого файла wsgi.py. Он даже не смотрит на manage.py

Итак, это восходит к тому, пытаетесь ли вы опубликовать сообщение после запуска вашего сервера. В этом случае это не зависит от Django или когда запускается ваше приложение Django?

Если вы пытаетесь распечатать что-либо после запуска приложения django, его инициализации и загрузки на сервер, у вас есть несколько вариантов. Если вы действительно хотите, вы можете отредактировать и добавить manage.py, но я бы не стал вмешиваться в ядро ​​Django дальше этого. Это будет полностью проигнорировано при использовании другого производственного сервера.

Если вы хотите отредактировать точку входа, которая будет загружаться независимо от используемого сервера, вы можете отредактировать модуль wsgi.py проекта или метод AppConfig отдельного приложения ready().

Если вы хотите создать что-то независимое от Django, которое постоянно работает в фоновом режиме, то, как указал @bruno-desthuilliers, вам нужно создать отдельный процесс либо как задание cron, либо с использованием сельдерея или даже django-моркови, если вы хотите, хотя последний все еще связан с запуском приложения, но может работать как отдельный воркер (я думаю). Django-морковь имеет только очень простые функции для небольших работ.

Извините, если это ничем не поможет, лучше всего я могу сделать с предоставленной информацией.


Я столкнулся с похожей проблемой, когда хотел что-то запустить внутри метода ready() моих приложений AppConfig. Для меня это был способ, которым мое приложение было установлено в моей переменной настройки INSTALLED_APPS.

Обычно вы регистрируете свои приложения следующим образом:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'my_app',
]

Однако это загрузит базовый класс AppConfig для регистрации ваших приложений. Если вы настраиваете и переопределяете AppConfig приложения, чтобы вы могли объявить свой собственный ready() метод, который будет выполняться после создания экземпляра приложения, вам необходимо обратиться к переопределенному AppConfig непосредственно в INSTALLED_APPS

So

INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'my_app.apps.MyAPPConfig', # MyAppConfig is the config class that inherits from AppConfig
    ]

В качестве альтернативы, если вы не хотите этого, сделайте это, когда конкретное приложение загружается через его AppConfig, поэтому не через метод ready(), а буквально, когда проект загружается на сервер, вы можете поместить в свой проект модуль wsgi.py после загрузки приложения

i.e

application = get_wsgi_application()
print('Hello World')

надеюсь, это поможет

person alfandango    schedule 02.01.2019
comment
см. мой комментарий к вопросу - что, если вы используете многопроцессорный сервер? - person bruno desthuilliers; 02.01.2019
comment
Вопрос состоит в том, чтобы запустить функцию, когда manage.py runserver завершит загрузку, которая является тестовым сервером, а не для производства. OP не дал понять, предназначена ли эта функция только для тестирования или для производства. Я интерпретирую это как после запуска приложения, как вы говорите, server start несколько двусмысленно. - person alfandango; 02.01.2019
comment
Прежде всего, ваш ответ такой же, как и этот из темы, которую я дал. Когда я пробовал это решение с простой печатью внутри ready(), я получаю на выходе 2-кратную печать, а затем выполняю проверку системы... в первую очередь это должно быть наоборот: сначала выполняется проверка системы преформирования... затем печать. В любом случае, когда я использую свою последнюю функцию, которая будет работать все время, я получаю AppRegistryNotReady: Apps aren't loaded yet - person KyluAce; 03.01.2019
comment
@KyluAce Я обновил свой ответ, но мне жаль, что я не совсем понимаю, что вы пытаетесь сделать. Это лучший ответ, который я могу дать, извините, если это не очень поможет. - person alfandango; 03.01.2019

Вы можете просто добавить вызов функции ближе к концу manage.py, в один из вспомогательных файлов, например routes.py, и так далее. Но! Вы указали, что хотите, чтобы функция вызывалась, когда сервер готов принимать запросы.

Переопределение AppConfig.ready() предназначено для случаев, когда вы создаете подкласс AppConfig и добавляете его в реестр приложений. Из вашего вопроса не ясно, следовали ли вы этой части. Вы можете еще раз убедиться, что следуете инструкциям здесь чтобы убедиться, что вы сделали это правильно.

person Charles Landau    schedule 02.01.2019
comment
На данный момент я почти уверен, что не могу использовать AppConfig.ready() с моей функцией, поэтому я попробовал функцию вызова в конце manage.py (у меня нет файла route.py в моем проекте), но я получаю AppRegistryNotReady: Apps aren't loaded yet. - person KyluAce; 03.01.2019
comment
Вы не можете использовать AppConfig.ready(), вы должны попытаться использовать SubclassOfAppConfig.ready() - person Charles Landau; 03.01.2019