Python 没有时间漂移的异步生成器函数

Python async generator function without time drift

我正在尝试模拟数字序列的生成,如下面的代码所示。我想在没有时间漂移的情况下定期执行此操作并且 without 跟踪调用 serial_sequence() 的次数,即不使用变量 。 如何做到这一点?

在示例代码中,delay2 始终为 0.1,但它应该稍微小一些,因为事件循环在调用 serial_sequence() 之间的其他地方很忙。因此经过的时间超过2.0秒。

import  asyncio
import time
rx_data = list()
EOT = 20

async def serial_sequence():
    '''async generator function that simulates incoming sequence of serial data'''
    num = 0
    tprev = time.time()

    while True:
        dt = time.time() - tprev
        delay2 = 0.1 - dt #Want to avoid time drift
        print('dt: {}'.format(dt))
        print('delay2: {}'.format(delay2))
        await asyncio.sleep(delay2) #simulated IO delay
        tprev = time.time()
        num += 1
        yield  num

async def read_serial1():
    gen = serial_sequence()
    while(True):
        data = await gen.__anext__()
        rx_data.append(data)
        print('read_serial1:', data)
        if data == EOT:
            break
    return rx_data

async def main():
    start = time.time()
    task1 = asyncio.create_task(read_serial1())
    await(task1)
    stop = time.time()
    print('Elapsed: {}'.format(stop-start))

if __name__ == '__main__':
    asyncio.run(main())

while 循环中的代码本身需要一些时间来计算。您的示例中的时间漂移​​会累积,因为您将 dt 基于前一个时间步 tprev.

的时间

您可以改为使用 serial_sequence 的绝对开始时间作为参考点,如下所示:

async def serial_sequence():
    '''async generator function that simulates incoming sequence of serial data'''
    num = 0
    starttime = time.time()

    while True:
        dt = (time.time() - starttime) % 0.1
        delay2 = 0.1 - dt #Want to avoid time drift
        print('dt: {}'.format(dt))
        print('delay2: {}'.format(delay2))
        await asyncio.sleep(delay2) #simulated IO delay
        tprev = time.time()
        num += 1
        yield num

通过改变EOT比较累加。 IE。加倍 EOT 会使您的解决方案的时间漂移​​加倍,而此解决方案的时间漂移​​大致不变。

我的回答主要基于 this answer to a very similar question