无全局状态的异步for循环的时间单次迭代

时间:2018-07-29 15:02:23

标签: python python-3.x python-asyncio

我正在尝试计时,并在程序中记录完成异步生成器+ for循环的单个迭代所花费的时间,而不用求助于全局状态。例如,给定

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之间的时间。

这怎么办?理想情况下,没有全局状态,理想情况下,时序代码与其余部分分离(例如使用装饰器)

2 个答案:

答案 0 :(得分: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 :(得分:1)

如果您只关心花费的时间,也许可以在run中进行计算。有一个例子,我认为它应该像我们只看async for loop一样工作,过程是线性的。

首先,end - start应该等于从pull()的第一次迭代到push(page)的结束的时间。然后使用end时间作为第二start时间,因此,这段时间end - start应该等于从pull()的第二次迭代到{{1 }}。

push(page)

如果我错了,请纠正我。