Python:Django: обработчик сигналов и основной поток

Я создаю приложение django, которое зависит от модуля python, в котором реализован обработчик сигнала SIGINT.

Предполагая, что я не могу изменить модуль, от которого я зависим, как я могу обойти ошибку "сигнал работает только в основном потоке", которую я получаю, интегрируя ее в Django?

Могу ли я запустить его в главном потоке Django? Есть ли способ запретить обработчику запускать модуль в неосновных потоках?

Спасибо!

4 ответа

Встроенный сервер разработки Django по умолчанию включает функцию автоматической перезагрузки, которая порождает новый поток как средство перезагрузки кода. Чтобы обойти это, вы можете просто сделать следующее, хотя вы, очевидно, потеряете удобство автоматической перезагрузки:

python manage.py runserver --noreload

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

Есть более чистый способ, который не нарушает вашу способность использовать потоки и процессы.

Поместите ваши регистрационные звонки в manage.py:

def handleKill(signum, frame):
    print "Killing Thread."
    # Or whatever code you want here
    ForceTerminate.FORCE_TERMINATE = True 
    print threading.active_count()
    exit(0)


if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

from django.core.management import execute_from_command_line

signal.signal(signal.SIGINT, handleKill)
signal.signal(signal.SIGTERM, handleKill)

execute_from_command_line(sys.argv)

Я использую Python 3.5 и Django 1.8.5 с моим проектом, и недавно я столкнулся с подобной проблемой. Я могу легко запустить мой xxx.py код с SIGNAL напрямую, но он не может быть выполнен на Django как пакет только из-за ошибки "сигнал работает только в основном потоке".

Во-первых, runserver с --noreload --nothreading можно использовать, но он запускает мой многопоточный код слишком медленно для меня.

Во-вторых, я нашел этот код в __init__.py моего пакета побежал в основной ветке. Но, конечно, только основной поток может перехватить этот сигнал, мой код в пакете вообще не может его перехватить. Это не может решить мою проблему, хотя, это может быть решением для вас.

Наконец, я обнаружил, что есть встроенный модуль с именем subprocess в Python. Это означает, что вы можете запустить субреальный завершенный процесс с ним, то есть этот процесс имеет свой собственный основной поток, так что вы можете легко запустить свой код с помощью SIGNAL здесь. Хотя я не знаю, как с ним работать, у меня это хорошо работает. PS, вы можете найти все подробности о subprocess в документации Python.

Спасибо ~

Хотя этот вопрос не описывает ситуацию, в которой вы находитесь, вот несколько общих советов:

Сигнал отправляется только в основной поток. По этой причине обработчик сигнала должен находиться в основном потоке. С этого момента действие, которое запускает сигнал, должно быть передано другим потокам. Я обычно делаю это, используя События. Обработчик сигнала устанавливает событие, которое будут прочитаны другими потоками, а затем поймет, что действие X было запущено. Очевидно, это подразумевает, что атрибут события должен быть общим для потоков.

Другие вопросы по тегам