Как вы останавливаете StreamingHttpResponse в Django, когда клиент отключается? - PullRequest
0 голосов
/ 20 февраля 2019

Мой сервер 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")

Это прямая трансляция с камеры, так что естьнет конца потоку.Мне нужно, чтобы он был прерван при отключении клиента, но пока я не могу понять, как определить, что клиент отключен.

Я что-то упустил?

Редактировать:

Чтобы устранить что-либо, связанное с камерой, я сделал это:

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")

и соединился с моим взглядом с помощью curl -N http://localhost/my_app/view_cam/.Это потоковые числа, и когда я прекращаю скручивать с помощью Ctrl + C, генератор просто продолжает работать бесконечно, не замечая, что клиент исчез.Если я запустлю и остановлю скручивание еще несколько раз, у меня будет несколько запущенных функций gen(), что и происходит с камерой.

Редактировать 2:

В этом проекте используетсяКаналы Джанго.Я только что заметил, что если я отключаю каналы, комментируя их в файле settings.py, приведенный выше пример работает отлично.Я не думал, что каналы были связаны с проблемой, но, видимо, это так или иначе.

Сервер разработки каналов действительно обнаруживает отключение через 10 секунд (не сразу, как сервер django по умолчанию), и показывалthis:

Вызов экземпляра приложения (), выполняемый в /home/pi/paperless_clipboard/venv3/lib/python3.5/site-packages/channels/http.py:213> wait_for = ._ call_check_cancel () в /usr/lib/python3.5/asyncio/futures.py:452, Task._wakeup ()] >> для соединения было слишком много времени, чтобы отключиться и было прервано.

, но несмотря насообщение о том, что что-то было убито, gen() продолжает работать, печатая номера на терминал.

1 Ответ

0 голосов
/ 20 февраля 2019

Вы не можете в соответствии с документами:

Соображения производительности Django предназначен для коротких запросов.Потоковые ответы свяжут рабочий процесс на все время ответа .Это может привести к снижению производительности.

Вообще говоря, вам следует выполнять дорогостоящие задачи вне цикла запрос-ответ, а не прибегать к потоковому ответу.

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

...