Время одной итерации асинхронного цикла без глобального состояния

1

Я пытаюсь время и записываю в программу, сколько времени требуется, чтобы завершить одну итерацию генератора асинхронного + для цикла, не прибегая к глобальному состоянию. Например, данный

import asyncio

async def run():
    async for page in pull():
      await push(page)

async def pull():
  for i in range(0, 3):
    print(f'Start of iteration {i}')
    await asyncio.sleep(1)
    yield i

async def push(i):
  await asyncio.sleep(1)
  print(f'End of iteration {i}')

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

что выходы

Start of iteration 0
End of iteration 0
Start of iteration 1
End of iteration 1
Start of iteration 2
End of iteration 2

Я хотел бы записать время между каждым началом Start of iteration i и следующим End of iteration i.

Как это может быть сделано? В идеале без глобального состояния и в идеале, когда временный код несколько отделен от остальных (например, с декораторами)

  • 0
    Не могли бы вы использовать асинхронный декоратор, чтобы обернуть вызов?
  • 0
    Просто идея: использовать модуль logging и печатать сообщения журнала с форматированием времени внутри?
Показать ещё 3 комментария
Теги:
python-3.x
python-asyncio

2 ответа

2

Вместо того, чтобы передавать вокруг i как целое число, вы можете передать структуру с некоторым состоянием. Вот пример увеличения i с некоторой информацией о времени:

Информация о сроках:

class TimerInt(int):
    def __new__(cls, *args, **kwargs):
        my_int = super(TimerInt, cls).__new__(cls, *args, **kwargs)
        my_int._start_time = time.time()
        return my_int

    @property
    def time_since_create(self):
        return time.time() - self._start_time

Это дает свойство int time_since_create которое может использоваться для некоторого грубого времени.

Тестовый код:

import asyncio
import time

async def run():
    async for page in pull():
        await push(page)

async def pull():
    for i in range(0, 3):
        i = TimerInt(i)
        print(f'Start of iteration {i}')
        await asyncio.sleep(1)
        yield i

async def push(i):
    await asyncio.sleep(1)
    print(f'End of iteration {i}: {i.time_since_create:.2f}')

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

Результаты теста:

Start of iteration 0
End of iteration 0: 2.01
Start of iteration 1
End of iteration 1: 2.00
Start of iteration 2
End of iteration 2: 2.00
1

Если вы просто заботитесь о затраченном времени, возможно, вы можете рассчитать их в run. Есть пример, я думаю, что он должен работать так, как будто мы просто смотрим на этот async for loop, этот процесс является линейным.

Сначала end - start должен быть равен времени от первой итерации pull() до конца push(page). И затем используйте end время как второе время start, поэтому этот end - start времени end - start должно совпадать со временем от второй итерации pull() до конца push(page) снова.

async def run():
    start = time.time()
    async for page in pull():
      await push(page)
      end = time.time()
      print("Cost {end - start} seconds")
      start = end

Если я ошибаюсь, поправьте меня, пожалуйста.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню