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。
我正在尝试模拟数字序列的生成,如下面的代码所示。我想在没有时间漂移的情况下定期执行此操作并且 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。