当我使用Ctrl+C退出Django的
manage.py runserver
命令时,正在运行HTTP请求的线程是否能够正常结束,还是会被中断?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
完成。
到目前为止一切都如预期。但是我稍微玩了一下,因为在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
Slept for: 10s
因此,在这里行为没有改变。出于兴趣,我改变了一行代码,但结果并没有改变;我使用了
slept_for = 1000*1000
time.sleep( 0.1 )
manage.py runserver
使用守护线程来提供响应,这意味着只要主线程完成,整个进程就会关闭,并且不会等待任何守护线程完成。由于 KeyboardInterrupt
在主线程中触发,而该线程没有提供任何响应,因此您无法在视图中捕获它,并且带有所有守护线程的进程立即退出。这就是为什么您的第二个示例仍然无法完成响应的原因。 - knbk