в моем проекте Django есть приложение, которое переопределяет его метод AppConfig.ready()
. В готовом методе я запускаю отдельный multiprocessing.Process
для обработки потребления из внешней очереди сообщений, похоже, это вызывает проблемы с автоперезагрузкой при изменении кода.
def infinite_loop():
while True:
time.sleep(10)
class BrokerConfig(AppConfig):
name = 'backend.broker'
has_started = False
def ready(self):
if not os.environ.get("RUN_MAIN"):
# Avoid running for reloader
return
if BrokerConfig.has_started:
return
BrokerConfig.has_started = True
proc = Process(target=infinite_loop)
proc.start()
По какой-то причине это приводит к прерыванию автоматической перезагрузки кода. Кажется, перезагрузка не может очистить запущенные процессы. Перезагрузчик печатает это, а затем зависает:
.../backend/broker/apps.py changed, reloading.
Способ обойти это — сделать запущенный процесс демоном, но если такая настройка невозможна, мне все еще любопытно, как вы могли бы обойти это.
Я ищу способ добавить пользовательскую очистку при перезагрузке, но я не могу найти способ сделать это. Есть ли какой-то хук или сигнал, на который вы можете подписаться, чтобы узнать, была ли запущена перезагрузка?
Мне удалось сделать это наоборот, поэтому вместо того, чтобы слушать или подключаться к какому-либо сигналу Django, чтобы указать «входящий перезагрузка кода», я добавил прослушиватель в свой запущенный процесс для SIGTERM. Когда происходит перезагрузка, перезагрузка кода приводит к завершению процессов демона и, таким образом, к получению сигнала SIGTERM. Я не нашел способа сделать это с процессами, не являющимися демонами.
def infinite_loop():
stop = False
def stop():
nonlocal stop
stop = True
signal.signal(signal.SIGTERM, stop)
while True:
if stop:
break
time.sleep(10)
class BrokerConfig(AppConfig):
name = 'backend.broker'
has_started = False
def ready(self):
if not os.environ.get("RUN_MAIN"):
# Avoid running for reloader
return
if BrokerConfig.has_started:
return
BrokerConfig.has_started = True
proc = Process(target=infinite_loop, daemon=True)
proc.start()
Итак, в конце концов я все-таки выбрал демона, и нужная мне очистка была помещена в область действия запущенного процесса (как обработчик SIGTERM).