2013-03-18 46 views
7

我有一個問題,我希望可以用Django中的某種形式的關閉鉤子解決。Django框架 - 是否有可以訂閱的關機事件?

我仍然使用Python/Django開發初學者,並幫助學習我已經給自己設定了發展彗星的項目/反轉,在瀏覽器中運行Ajax風格的聊天網站。瀏覽器不斷查詢服務器是否有任何消息。當服務器收到輪詢請求時,它會檢查是否有任何消息在等待,如果沒有消息,它將嘗試獲取已獲取的對象的線程鎖定。這會導致處理請求的線程阻塞,直到收到消息並釋放前面提到的鎖。

我關閉服務器時出現問題。此時我正在使用開發服務器(python manage.py runserver)。如果有一個線程被上面解釋的進程阻塞,那麼服務器不會關閉。

有沒有一種方法可以在服務器嘗試關閉時執行代碼,以便我可以釋放任何等待的線程?

我看了下面的similar question但是它沒有幫助我。有人猜測,這樣的事件掛鉤不存在,但沒有明確的答案。我已經高高在上,但一直沒有運氣。

我使用Python 2.7和Django 1.5。

感謝任何幫助,您可以提供

+0

不太確定這是如何實現的,如果這樣做會工作,但我會把它放在那裏 - 關閉的消息,所有線程都會讀和理解爲「哦,我應該停止」? – dmg 2013-03-18 08:17:48

+0

@DJV:但我怎麼知道發送該消息? – 2013-03-18 08:35:58

+0

不太確定,開發服務器的'Ctrl + C'(a.k.a.' KeyboardInterrupt')的某種處理。對於不同的服務器,可能會想到不同的方法。我明白,這不是一個通用的方法,它不是通過Django完成的,但正如我所說的「我只是把它拋出去」。 – dmg 2013-03-18 08:39:43

回答

4

我不知道關閉事件,但你可以創建一個。

當用戶按下Ctrl-C時,一個SIGINT信號被髮送到Python進程。從wsgi.py文件中設置一個信號處理程序來捕獲SIGINT並將其轉發到您的程序。

wsgi.py:

... 

import signal 
signal.signal(signal.SIGINT, my_signal_handler) 

您可以在信號甚至轉發到Django的信號:

my_django_shutdown_signal = django.dispatch.Signal() 

def _forward_to_django_shutdown_signal(signal, frame): 
    my_django_shutdown_signal.send('system') 
    sys.exit(0) # So runserver does try to exit 
signal.signal(signal.SIGINT, _forward_to_django_shutdown_signal) 

由於signal只能從主線程調用,這不會與工作runserver命令。要麼與--noreload選項呼叫運行服務器,要麼切換到gunicorn。

+0

任何想法如何在Apache和mod_wsgi中獲得此行爲? – Ward 2015-07-30 11:19:32

2

通過添加骨鈣斯圖回答:
要在Django設置信號事件處理程序在主線程可以放放的處理,以manage.py初始化或您的應用程序的__init__.py,像這樣:

# {project_root}/{your_app}/__init__.py 
import os 
import signal 
import sys 
def my_signal_handler(*args): 
    if os.environ.get('RUN_MAIN') == 'true': 
     print('stopped'.upper()) 
    sys.exit(0) 

signal.signal(signal.SIGINT, my_signal_handler) 

它會讓你運行服務器沒有- 無負載
檢查os.environ.get('RUN_MAIN') pvevent調用函數2次。