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

4
当我使用Ctrl+C退出Django的manage.py runserver命令时,正在运行HTTP请求的线程是否能够正常结束,还是会被中断?

我相信 Ctrl+C 会杀死进程以及所有与主线程相关的子进程。因此,它们将在中途被打断。您可以使用 ps -eLf(Linux、Unix)列出所有线程来进行双重确认。 - reticentroot
1个回答

5

TL;DR 当在 Django 开发服务器上按下 Ctrl+C 时,正在运行的 HTTP 请求会停止。

我认为您的问题非常有趣,于是进行了调查:

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

我的基本测试:

class TestView ( generic.View ):
    def get ( self, request ):
        import time
        time.sleep(10)
        response = HttpResponse('Done.')
        return response
  • 正常执行(运行10秒):显示消息完成。
  • 中断执行(在请求正在运行时按下Ctrl+C):浏览器错误,无法到达主机。

到目前为止一切都如预期。但是我稍微玩了一下,因为在Python中,Ctrl+C不是一个完整的停止符号,而实际上它被处理得相当方便:一旦按下Ctrl+C,就会引发一个KeyboardInterrupt异常(相当于这个):

raise KeyboardInterrupt()

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

try:
    some_action_that_takes_a_while()
except KeyboardInterrupt:
    print('The user stopped the programm.')

将新视图移植到 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
  • 普通执行(10秒运行时间):显示消息Slept for: 10s
  • 被中断的执行(Ctrl+C,当请求正在运行时):浏览器错误,无法到达主机

因此,在这里行为没有改变。出于兴趣,我改变了一行代码,但结果并没有改变;我使用了

slept_for = 1000*1000

代替
time.sleep( 0.1 )

所以最终回答你的问题是:按下Ctrl+C后,开发服务器会立即关闭,并且正在运行的http请求不会被完全执行

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接