Отправляйте асинхронные HTTP-запросы один за другим - PullRequest
0 голосов
/ 05 февраля 2020

Я пытаюсь использовать aiohttp для отправки запросов один за другим, как это

import aiohttp
import asyncio
from datetime import datetime


async def main():
    request_url = "https://..."
    async with aiohttp.ClientSession() as session:
        while True:
            print(datetime.now())
            async with session.get(request_url) as response:
                json_data = await response.json()
            print(json_data)
            await asyncio.sleep(0.2)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Так что я бы ожидал, что каждая печать даты и времени будет с интервалом 0,2 с. Однако, кажется, что они находятся на расстоянии около 0,35 с, так как я думаю, что для получения данных из ответа требуется 0,15 с. Почему это происходит? Я хочу, чтобы он был асинхронным, поэтому он должен просто go перейти к следующему?

Как я могу это исправить?

Спасибо.

Ответы [ 2 ]

1 голос
/ 06 февраля 2020

Отправка http-запроса и получение ответа занимает некоторое время. Вам нужно исключить это время из asyncio.sleep() звонить:

import aiohttp
import asyncio
import time
from datetime import datetime


async def main():
    request_url = "https://..."
    async with aiohttp.ClientSession() as session:
        while True:
            print(datetime.now())
            t0 = time.monotonic()
            async with session.get(request_url) as response:
                json_data = await response.json()
            print(json_data)
            t1 = time.monotonic()
            await asyncio.sleep(0.2 - (t1 - t0))


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
0 голосов
/ 05 февраля 2020

Когда вы используете await весь следующий код будет ждать конца этого кода. Если вы хотите выполнять асинхронный код асинхронно, вы должны использовать такие функции, как asyncio.gather


import asyncio
import aiohttp
import datetime


async def fetch(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            print('#', response.status)


async def worker(queue):
    print('START WORKER')
    while True:
        url = await queue.get()
        await fetch(url)
        queue.task_done()


async def control(queue):
    while True:
        print(datetime.datetime.now())
        queue.put_nowait('https://docs.python.org/')
        await asyncio.sleep(0.2)


async def main():
    queue = asyncio.Queue()
    await asyncio.gather(
        control(queue),
        asyncio.gather(*[worker(queue) for _ in range(10)])
    )


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

...