[英]How do I stop Django development server from restarting?
我希望Django開發服務器在發生錯誤時退出。 但是只要服務器退出,它就會重新啟動。 我試圖使用os.kill(os.getpid,9)終止進程,但無法正常工作。 我嘗試了sys.exit,os._exit,並引發了錯誤,但沒有一個起作用。
注意:由於該程序不僅可以在Linux上運行,因此理想情況下,我不希望使用bash之類的東西。 我也不想破壞其他過程。
開發服務器不會因錯誤而重啟,它只會處理異常並繼續運行,就像生產服務器一樣。 這就是應該的樣子– HTTP是無狀態的,一個請求中的錯誤不應影響下一個請求。
因此,您需要知道,無論您在做什么, 都可能在濫用runserver
,並且幾乎肯定有一種更好的方法。
說:
有幾個地方可以防止服務器因錯誤退出。
首先,Django將每個請求包裝在django.core.handlers.exception.convert_exception_to_response
函數中,該函數捕獲每個Exception
並將其轉換為一個不錯的響應。 因此,要解決此問題,您需要引發一個不是從Exception
派生的錯誤,例如KeyboardInterrupt
或SystemExit
。
然后是django.core.servers.basehttp.ServerHandler
,它是從wsgiref.handers.BaseHandler
派生的,該請求將try: ... except: ...
的請求包裝起來try: ... except: ...
以捕獲所有異常,然后再次將它們轉換為響應。 由於您可能仍想獲得該響應,因此您必須修改handle_error
方法以在生成錯誤響應后再次引發錯誤。
不幸的是,那里有很多耦合。 ServerHandler
類被硬編碼為django.core.servers.basehttp.WSGIRequestHandler.handle
,其被硬編碼為django.core.server.basehttp.run
,其被硬編碼為django.core.management.commands.runserver
因此,您要么必須復制所有代碼(基本上就是Django所做的,就是從wsgiref
復制一些代碼),要么您只剩下猴子補丁了。
然后還有django.core.servers.basehttp.WSGIServer
,它是socketserver.BaseServer
的子類。 我們剛剛提出的異常現在進入WSGIServer.handle_error
,它將嘗試將其變成響應並繼續。 因此,您需要覆蓋它。
然后,只要您運行從runserver派生的自定義命令,就可以在沒有線程且無需重新加載的情況下運行服務器的情況下工作,如下所示:
import sys
from django.core.management.commands import runserver
from django.core.servers.basehttp import ServerHandler, is_broken_pipe_error, WSGIServer
good_handle_error = ServerHandler.handle_error
def bad_handle_error(self):
if not is_broken_pipe_error():
good_handle_error(self)
sys.exit(1)
ServerHandler.handle_error = bad_handle_error
class BadWSGIServer(WSGIServer):
def handle_error(self, request, client_address):
if is_broken_pipe_error():
super().handle_error(self, request, client_address)
else:
sys.exit(1)
class Command(runserver.Command):
server_cls = BadWSGIServer
def handle(self, *args, **options):
options['use_reloader'] = False
options['use_threading'] = False
super().handle(*args, **options)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.