`manage.py runserver` 和 Ctrl+C (Django)

por*_*ton 4 python django signals

manage.py runserver当我使用Ctrl+退出 Django 时C,运行 HTTP 请求的线程是否正确完成,还是在中间中断?

小智 5

TL;DR当在 django 开发服务器上点击Ctrl+时,运行 HTTP 请求将停止C

我认为你的问题非常有趣并进行了调查:

我创建了一个需要 10 秒执行然后发送响应的视图。manage.py runserver为了测试您的行为,我使用Ctrl+停止了开发服务器C并检查结果。

我的基础测试:

class TestView ( generic.View ):
    def get ( self, request ):
        import time
        time.sleep(10)
        response = HttpResponse('Done.')
        return response
Run Code Online (Sandbox Code Playgroud)
  • 正常执行(10s运行时间):显示msgDone.
  • 中断执行(Ctrl+C当请求正在运行时):浏览器错误,无法到达主机

到目前为止一切都如预期。但我玩了一下,因为python 中的Ctrl+不是句号,但实际上处理起来相当方便:一旦+被击中,就会出现一个又名异常(相当于这个):CCtrlCKeyboardInterrupt

raise KeyboardInterrupt()
Run Code Online (Sandbox Code Playgroud)

因此,在基于命令行的程序中,您可以输入以下内容:

try:
    some_action_that_takes_a_while()
except KeyboardInterrupt:
    print('The user stopped the programm.')
Run Code Online (Sandbox Code Playgroud)

移植到 django 后,新视图如下所示:

def get ( self, request ):
    import time
    slept_for = 0
    try:
        for i in range( 100 ):
            slept_for += 0.1
            time.sleep( 0.1 )
    except KeyboardInterrupt:
        pass

    response = HttpResponse( 'Slept for: ' + str( slept_for ) + 's' )
    return response
Run Code Online (Sandbox Code Playgroud)
  • 正常执行(10s运行时间):显示msgSlept for: 10s
  • 中断执行(Ctrl+C当请求正在运行时):浏览器错误,无法到达主机

所以这里的行为没有改变。出于兴趣,我改变了一行,但结果没有改变;我用了

slept_for = 1000*1000
Run Code Online (Sandbox Code Playgroud)

代替

time.sleep( 0.1 )
Run Code Online (Sandbox Code Playgroud)

所以最后回答你的问题: on Ctrl+C开发服务器立即关闭并且运行 http-requets尚未完成

  • 默认情况下,“manage.py runserver”使用守护线程来提供响应,这意味着一旦主线程完成,整个进程就会关闭,并且不会等待任何守护线程完成。由于“KeyboardInterrupt”是在主线程中触发的,该线程不提供任何响应,因此您无法在视图中捕获它,并且所有守护线程的进程都会立即退出。这就是为什么你的第二个例子仍然没有完成响应。 (4认同)