Канал Django для веб-сокетов не является действительно асинхронным? - PullRequest
0 голосов
/ 22 декабря 2018

Я написал код каналов django для асинхронной отправки данных API из двух разных источников через веб-сокеты.Различные источники занимают от нескольких секунд до 1 минуты для вычисления и отправки данных.Мне удалось вызвать их асинхронно, используя цикл событий asyncio.Но проблема в том, что они не отправляют ответ обратно асинхронно.Код просто ожидает поступления всех данных и отправляет все одновременно.

Код канала:

class SearchHotelConsumer(AsyncWebsocketConsumer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.source1 = Source1()
        self.source2 = Source2()

    async def connect(self):
        await self.accept()

    def disconnect(self, close_code):
        pass

    async def _source1_handler(self, request, queue):
        source1_response = await self.source1.async_post(request)

        await queue.put(source1_response.data)

    async def _source2_handler(self, request, queue):
        source2_response = await self.source2.async_post(request)

        await queue.put(source2_response.data)

    async def _send_msg(self, queue):
        while True:
            message = await queue.get()
            if message is None:
                break
            print('got the message')
            await self.send(text_data=json.dumps({
                'message': message
            }, cls=DjangoJSONEncoder))

            queue.task_done()

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        request = HttpRequest()
        request.method = 'POST'
        request.session = self.scope["session"]
        request = Request(request)
        for key, val in message.items():
            request.data[key] = val

        queue = asyncio.Queue()
        sender = asyncio.ensure_future(self._send_msg(queue))

        await self._source1_handler(request, queue)
        await self._source2_handler(request, queue)

        await queue.join()

        sender.cancel()

Как сделать часть отправки сообщения действительно асинхронной?

1 Ответ

0 голосов
/ 28 декабря 2018

Ваш код async_post, который не показан, вероятно, является синхронным.

Если вы хотите асинхронные запросы, посмотрите этот ответ:

https://stackoverflow.com/a/22414756/10840818

Чтобы использовать запросы (или любые другие блокирующие библиотеки) с asyncio, вы можете использовать BaseEventLoop.run_in_executor для запуска функции в другом потоке и выдачи из нее результата для получения результата.

Или альтернатива способу http получить асинхронность

async with aiohttp.ClientSession() as session:
        async with session.get(url, headers=HEADERS, params=params) as resp:
            data = await resp.json()
...