使用 asyncio 编写 pyModbus 服务器。 除了服务器之外,我还有一个正在与之通信的串行设备和一个服务器更新任务。 一个任务应该每 500 毫秒检查一次串行设备的状态。 服务器更新任务应该检查串行设备的状态是否有任何变化并更新服务器上的信息。此外,如果服务器上有请求等待,它应该调用另一个任务,该任务将必要的信息发送到串行设备。
我的三个问题是:
aiocron
谢谢!
编辑:
说到运行周期性任务并取消它们 - 这是正确的做法吗?这不会引发任何错误,但它能正确清理所有内容吗?(我创建了这个草图,汇集了十几个关于 stackoverflow 的问题,我不确定这是否有意义)
import asyncio async def periodic(): try: while True: print('periodic') await asyncio.sleep(1) except asyncio.CancelledError as ex: print('task1', type(ex)) raise async def periodic2(): try: while True: print('periodic2') await asyncio.sleep(0.5) except asyncio.CancelledError as ex: print('task2', type(ex)) raise async def main(): tasks = [] task = asyncio.create_task(periodic()) tasks.append(task) task2 = asyncio.create_task(periodic2()) tasks.append(task2) for task in tasks: await task if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: pass
仅供参考:我正在逐一写下你的问题的答案,以便任何遇到这个问题的人都能理解你是如何最终得到一些编辑结果的,同时也能添加如何在不破坏任何东西的情况下取消任务的答案。
您可以通过捕获信号(由 Ctrl+C 触发)来处理 asyncio 应用程序的正常关闭KeyboardInterrupt,然后取消正在运行的任务并关闭资源。以下是如何执行此操作的示例:
KeyboardInterrupt
import asyncio async def main(): # Your other tasks and setup here try: loop = asyncio.get_event_loop() loop.run_until_complete(main()) except KeyboardInterrupt: print("Received Ctrl+C. Stopping gracefully...") # Cancel all running tasks for task in asyncio.Task.all_tasks(): task.cancel() # Optionally: Close any open resources (sockets, files, etc.) # Cleanup code here finally: loop.close()
要使用 asyncio 循环运行任务,您可以在任务中使用 asyncio.sleep 函数。这是一个基本示例:
import asyncio async def task_to_run(): while True: # Your cyclic task code here await asyncio.sleep(0.5) # Sleep for 500ms (0.5 seconds) async def main(): task = asyncio.create_task(task_to_run()) # Your other tasks and setup here
此代码每 500ms 执行一次task_to_run。您可以根据需要调整睡眠时间。
task_to_run
如正常停止服务器的代码示例所示(在 Ctrl+C 处理部分),您可以使用task.cancel()它在停止服务器之前礼貌地取消所有正在运行的任务。这可确保任何正在进行的任务都有机会在退出之前进行清理
task.cancel()