#python #django #server #neural-network
#python #django #сервер #нейронная сеть
Вопрос:
Мы используем Django в качестве серверной части для веб-сайта, который предоставляет различные функции, среди прочего, используя нейронную сеть, использующую Tensorflow для ответа на определенные запросы.
Для этого мы создали AppConfig
и добавили загрузку конфигурации этого приложения INSTALLED_APPS
в Django settings.py
. Этот AppConfig затем загружает Нейронную сеть, как только она будет инициализирована:
settings.py:
INSTALLED_APPS = [
...
'bert_app.apps.BertAppConfig',
]
…/bert_apps/app.py:
class BertAppConfig(AppConfig):
name = 'bert_app'
if 'bert_app.apps.BertAppConfig' in settings.INSTALLED_APPS:
predictor = BertPredictor() #loads the ANN.
Теперь, пока это работает и делает то, что должно, ANN теперь загружается для каждого выполнения отдельной команды manage.py
. Хотя мы, конечно, хотим, чтобы он выполнялся при вызове manage.py runserver
, мы не хотим, чтобы он выполнялся для manage.py migrate
или manage.py help
и всех других команд.
Я вообще не уверен, правильно ли это загружать ANN для Django-серверной части в целом, так есть ли у кого-нибудь какие-нибудь советы, как это сделать правильно? Я могу себе представить, что загрузка модели при запуске — не совсем лучшая практика, и я очень открыт для предложений о том, как сделать это правильно.
manage.py runserver
Однако, помимо фактической загрузки модели, есть и другой код, который также занимает несколько секунд и который, безусловно, должен выполняться сразу после запуска сервера (и так далее manage.py help
), но также не включен (поскольку это также занимает несколько секунд), так что есть ли какой-нибудь быстрыйисправлено, как указать Django выполнять его только для runserver
, а не для других его команд?
Комментарии:
1. Ваши фрагменты кода выглядят так, как будто вы смешивали код Django и Flask.
2. «Я вообще не уверен, что это правильный способ загрузки» -> как правило, правильный способ инициализации любых дополнительных функций — из вашего AppConfig. Однако обратите внимание, что это будет сделано перед разветвлением. В зависимости от используемого вами веб-сервера у вас может быть несколько процессов, и они могут быть остановлены посередине. Таким образом, если ваша нейронная сеть должна сохранять некоторые данные в оперативной памяти во всех запросах, то вам может потребоваться совершенно другой подход.
3. @KlausD. Почему ты так думаешь? Что для вас похоже на код Flask?
4. @Art То есть вы имеете в виду, что в целом то, что мы здесь сделали, правильно до тех пор, пока мы не используем несколько процессов? Что бы вы предложили на случай, если мы это сделаем? Мое первоначальное предложение состояло в том, чтобы использовать модель в качестве микросервиса, но команда сказала мне, что это будет чрезмерно…
5. @ChrisStenkamp ну, вы также всегда можете выстрелить себе в ногу без многопроцессорной обработки 🙂 То, что вы сделали, правильно, если вам не нужно сохранять измененное состояние ANN между запросами. Во-первых, ответьте на следующий вопрос: обновляют ли запросы ваше состояние ANN в памяти таким образом, что вы хотите увидеть это обновленное состояние при выполнении следующего веб-запроса? Если нет, продолжайте то, что вы делаете. Если да, что ж, все становится сложнее: вам нужно запускать ANN отдельно (например, в отдельном manage.py команда) и использовать некоторую форму IPC / RPC для связи с ним.
Ответ №1:
У меня была похожая проблема, я решил ее проверкой argv
.
class SomeAppConfig(AppConfig):
def ready(self, *args, **kwargs):
is_manage_py = any(arg.casefold().endswith("manage.py") for arg in sys.argv)
is_runserver = any(arg.casefold() == "runserver" for arg in sys.argv)
if (is_manage_py and is_runserver) or (not is_manage_py):
init_your_thing_here()
Теперь немного ближе к if not is_manage_py
сути: в рабочей среде вы запускаете свой веб-сервер с помощью uwsgi/ uvicorn/ …, который по-прежнему является веб-сервером, за исключением того, что он не запускается manage.py
. Скорее всего, это единственное, без чего вы когда-либо будете бегать manage.py
Используйте AppConfig.ready()
— это предназначено для этого:
Подклассы могут переопределять этот метод для выполнения задач инициализации, таких как регистрация сигналов. Он вызывается, как только реестр будет полностью заполнен. — [документация django]
Чтобы получить свою AppConfig
спину, используйте:
from django.apps import apps
apps.get_app_config(app_name)
# apps.get_app_configs() # all
Комментарии:
1. Спасибо, кажется, это работает! 🙂 Однако одно но: пока мы даже не создаем экземпляр AppConfig (как вы видите в вопросе,
predictor
это просто атрибут класса). Поэтому, когда мы используем его, мы используемfrom bert_app.apps import BertAppConfig
BertAppConfig.predictor.do_stuff()
в другом месте. В вашем ответе AppConfig, похоже, является ООП. Как мы могли бы получить доступ к экземпляру этого позже? Может быть, синглтон-паттерн? И когдаready()
будет вызван Django?2. @ChrisStenkamp django создаст для вас его экземпляр. Используйте
ready()
метод, он специально создан для этого. Чтобы получить объект, который вы создали внутри вашегоAppConfig
, просто получите вашAppConfig
, или даже сохраните его в какой-нибудь глобальной переменной для всего модуля (лучше не вapps.py
, а где-нибудь еще). И, пожалуйста, пожалуйста, не внедряйте свои собственные синглтоны в Python — для этого есть модули. Я обновил ответ информацией обAppConfig
этом.
Ответ №2:
Это другой способ, в вашем manage.py будет что-то, вероятно, выглядеть так
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'slambook.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
# check if has runserver
if `runserver` in sys.argv:
#execute your custom function
if __name__ == '__main__':
main()
вы можете проверить sys.argv
, есть ли у него runserver
, если да, то выполните свой скрипт или функцию
Комментарии:
1. Но, делая это таким образом, ничего не загружается в другие команды, кроме runserver, и, например
help
, команды просто завершаются, ничего не возвращая..