You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python async generator无时间漂移、不计调用次数的定间隔实现咨询

实现方案

以下是满足需求的修改后代码,完全无需计数变量、无时间漂移,总运行时长稳定接近2.0s:

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

async def serial_sequence():
    '''async generator function that simulates incoming sequence of serial data'''
    interval = 0.1
    start_time = time.time()
    next_run = start_time + interval

    while True:
        now = time.time()
        dt = now - (next_run - interval)
        delay = max(0, next_run - now)
        print('dt: {}'.format(dt))
        print('delay2: {}'.format(delay))
        await asyncio.sleep(delay) #simulated IO delay
        current_val = round((next_run - start_time) / interval)
        next_run += interval
        yield current_val

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())

关键改动说明

  • 完全移除了计数变量num:通过初始启动时间和每次触发的锚点时间的差值,自动计算当前返回的序列值,不需要统计生成器的调用次数
  • 从根源避免时间漂移:维护next_run作为下一次触发的绝对时间锚点,每次触发后直接累加固定间隔0.1s,不管单次任务处理、事件循环调度耗时多久,永远对齐初始的时间步长,不会产生累计误差
  • 增加异常兼容:如果事件循环被其他任务占用过久,导致当前时间已经超过预期触发时间,会自动将sleep时长设置为0,避免参数报错同时快速补触发消除滞后

内容的提问来源于stack exchange,提问作者mr_js

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 18:27:02