Python 在时间间隔内运行异步IO循环
目标:运行Python 在时间间隔内运行异步IO循环,python,python-asyncio,Python,Python Asyncio,目标:运行main(),包括start\u time和end\u time import datetime as dt start_time, end_time= dt.time(9, 29), dt.time(16, 20) current\u time()只是不断地将当前时间添加到工作空间中。此时间用于此处未显示的脚本中的几个不同点 async def current_time(): while True: globals()['now'] = dt.datet
main()
,包括start\u time
和end\u time
import datetime as dt
start_time, end_time= dt.time(9, 29), dt.time(16, 20)
current\u time()
只是不断地将当前时间添加到工作空间中。此时间用于此处未显示的脚本中的几个不同点
async def current_time():
while True:
globals()['now'] = dt.datetime.now().replace(microsecond=0)
await asyncio.sleep(.001)
另一个做某事的函数:
async def balance_check():
while True:
#do something here
await asyncio.sleep(.001)
main()
等待前面的协同程序:
async def main():
while True:
#Issue:This is my issue. I am trying to make these
#coroutines only run between start_time and end_time.
#Outside this interval, I want the loop to
#shut down and for the script to stop.
if start_time < now.time() < end_time :
await asyncio.wait([
current_time(),
balance_check(),
])
else:
print('loop stopped since {} is outside {} and {}'.format(now, start_time, end_time))
loop.stop()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(main())
finally:
loop.close()
async def main():
尽管如此:
#问题:这是我的问题。我正试着做这些
#协同路由仅在开始时间和结束时间之间运行。
#在此间隔之外,我希望循环
#关闭并使脚本停止。
如果开始时间
问题:即使在结束时间后仍能继续工作问题在于不正确使用了
wait asyncio.wait([current_time(),balance_check(),])
waitingasyncio.wait()
等待指定的等待项完成,即返回值或引发异常。由于current\u time
和balance\u check
都不会从无限循环中返回,因此main()
的执行永远不会通过wait asyncio.wait(…)
,因为此表达式等待这两个循环完成。反过来,main()
中的while
循环永远不会进入第二次迭代,loop.stop()
没有机会运行
如果代码的目的是使用asyncio.wait()
来给协同程序一个运行的机会,那么asyncio.wait
就不是这个工具。相反,可以通过调用asyncio.create_task()
来启动这两个任务,然后什么也不做。只要事件循环可以运行(即,它没有被调用time.sleep()
或类似功能阻止),asyncio将自动在协同程序之间切换,在这种情况下,current\u time
和balanced\u check
以~1毫秒的速度切换。当然,您希望在结束时间
截止日期之前重新获得控制权,因此“什么也不做”最好表示为对asyncio.sleep()的单个调用:
请注意,甚至不需要显式的loop.stop()
,因为run\u until\u complete()
将在给定的协同程序完成后自动停止循环。对任务调用cancel()
没有实际效果,因为循环几乎立即停止;它是用来完成这些任务的,这样垃圾回收器就不会在销毁挂起的任务时发出警告
如注释中所述,此代码不会等待开始时间
,但在生成任务之前,通过添加另一个睡眠可以轻松完成此功能。您可以使用此功能,特别是事件
将日期时间导入为dt
导入异步
异步定义函数(开始事件、结束事件):
#等待,直到我们获得启动事件命令。
等待启动事件。等待()
#运行函数,直到将end_事件设置为true。
索引=0
而不是结束\u事件。是否设置了\u()
打印(f“函数正在运行;索引{index}.”)
等待异步睡眠(2)
指数+=1
异步def控制器(开始事件、结束事件):
#通常是这样。出于测试目的注释掉。可以通过主干道。
#减法/加法在dt.datetime()上不起作用。不平等是(>或者你的问题是什么?你展示的代码有什么问题?@mkrieger1 edited如果我错了,请纠正我,但我正在试图理解你为什么要这样做。我所能想到的是你(1)想先运行一个函数,或者从其他地方调用另一个函数,(2)您希望在特定时间运行函数,或(3)你这样做是为了练习?我不确定。你能指定吗?你必须使用asyncio吗?@FelipeFaria在这个脚本中,我同时使用asyncio和循环运行一系列函数/协同程序。但是我希望整个脚本只在开始时间和结束时间之间运行。谢谢你的澄清答案。能够使用asyncio.create_task
我不得不升级到Python>3.7。现在,当我使用你的main()
而不是我的时,我得到RuntimeError:当另一个循环正在运行时无法运行事件循环。
当我去掉整个循环对象(上面代码的最后6行)而改用asyncio.run(main())
,我得到运行时错误:无法从正在运行的事件循环调用asyncio.run()
有什么想法吗?@FelipeFaria您的评论不正确-与协同程序对象不同,任务不必等待执行,它们由事件循环“在后台”自动执行。如果你不相信,你可以简单地从答案中运行代码,并注意到它是有效的。没问题,现在我只希望我能摆脱否决票。:)关于等待开始
,这很简单,只需在生成任务之前添加睡眠即可。@FelipeFaria进行了编辑(关于等待开始时间的信息),谢谢你的坦率!@user4815162342当然——我们在这里应该是诚实的
async def main():
t1 = asyncio.create_task(current_time())
t2 = asyncio.create_task(balance_check())
end = dt.datetime.combine(dt.date.today(), end_time)
now = dt.datetime.now()
await asyncio.sleep((end - now).total_seconds())
print('loop stopped since {} is outside {} and {}'.format(now, start_time, end_time))
t1.cancel()
t2.cancel()