当客户端断开连接时,如何在Django中停止StreamingHttpResponse?

Joh*_*ohn 5 python django python-3.x django-channels

我的django服务器以jpeg流的形式一次播放一帧视频。

看起来像这样:

class VideoCamera():
    def __init__(self):
        # code

    def get_frame(self):
        # code
        return frame

def gen(camera):
    while True:
        yield camera.get_frame()

def view_cam(request):
    return StreamingHttpResponse(gen(VideoCamera()), content_type="multipart/x-mixed-replace;boundary=frame")
Run Code Online (Sandbox Code Playgroud)

这是实时的摄像头提要,因此流无止境。我需要在客户端断开连接时将其中断,但是到目前为止,我仍无法弄清如何检测到客户端断开连接。

我想念什么吗?

编辑:

为了消除与相机有关的一切,我这样做:

def gen():
    for i in range(1000):
        time.sleep(1)
        print(i)
        yield i

def view_cam(request):
    return StreamingHttpResponse(gen(), content_type="multipart/x-mixed-replace;boundary=frame")
Run Code Online (Sandbox Code Playgroud)

并通过链接到我的视图curl -N http://localhost/my_app/view_cam/。它流传输数字,当我停止使用Ctrl + C进行卷曲时,生成器只是无限期地运行,而没有注意到客户端消失了。如果再运行几次并停止卷曲,则我的gen()功能会运行多个实例,这正是相机发生的情况。

编辑2:

该项目使用Django Channels。我只是注意到,如果我通过在settings.py中将其注释掉来禁用频道,则上面的示例可以完美地工作。我不认为渠道与问题有关,但很明显,这与某种原因有关。

频道开发服务器实际上会在10秒后检测到断开连接(不是像默认的django服务器那样立即检测到),并显示以下内容:

在/home/pi/paperless_clipboard/venv3/lib/python3.5/site-packages/channels/http.py:213>上运行的应用程序实例call()在/usr/lib/python3.5/ asyncio / futures.py:452,Task._wakeup()] >>用于连接的时间过长,无法关闭并被杀死。

但是尽管有消息说有人被杀死,但仍gen()继续运行,并向终端打印号码。

Ray*_*nda 1

你不能根据文档:

性能考虑 Django 是为短期请求而设计的。流式响应将在整个响应期间绑定一个工作进程。这可能会导致性能不佳。

一般来说,您应该在请求-响应周期之外执行昂贵的任务,而不是诉诸流式响应。

https://docs.djangoproject.com/en/2.1/ref/request-response/#streaminghttpresponse-objects