Python Asyncio:为何两个无限循环异步函数无法并发运行?
问题根源
你的代码里的_wait_new_file和_check_difference是同步阻塞的无限循环,完全霸占了asyncio的单线程事件循环,导致第二个任务根本没机会被调度执行。
asyncio的事件循环依赖任务主动让出CPU(通过await异步操作)来实现并发。而你的两个_sync方法里是纯同步的死循环,没有任何await语句或让出控制权的逻辑,一旦第一个任务启动,就会一直占用事件循环,其他任务永远得不到运行机会。
修复方案
核心是把同步循环改成异步循环,在每次循环中加入await asyncio.sleep(xxx)让出CPU,同时优化文件操作逻辑:
import asyncio import os class Program: def __init__(self): self.files = set(os.listdir('data')) # 用集合替代列表,集合差集运算更高效 self.last_file = '' self.history = [] async def wait_new_file(self): await self._wait_new_file() async def _wait_new_file(self): # 改为异步方法 while True: checked_files = set(os.listdir('data')) # 处理新增文件 if new_files := checked_files - self.files: for new_file in new_files: print(f'{new_file = }') self.last_file = new_file self.files.add(new_file) self.history.append(f'>>> {new_file}') print(f'{self.files = }') # 处理删除文件 if deleted_files := self.files - checked_files: for deleted_file in deleted_files: print(f'{deleted_file = }') self.files.remove(deleted_file) print(f'{self.files = }') # 终止条件 if os.path.exists('stop'): print(self.history) return await asyncio.sleep(0.1) # 让出CPU,让其他任务执行 async def check_difference(self): await self._check_difference() async def _check_difference(self): # 改为异步方法 flip = True while True: current_exists = os.path.exists('flip') if flip and current_exists: flip = False print('on') elif not flip and not current_exists: flip = True print('off') # 终止条件 if os.path.exists('stop'): return await asyncio.sleep(0.1) # 让出CPU async def main(self): async with asyncio.TaskGroup() as tg: task_check_difference = tg.create_task(self.check_difference()) task_monitor_files = tg.create_task(self.wait_new_file()) program = Program() asyncio.run(program.main())
关键修改点
- 将两个_sync方法改为异步方法(添加
async关键字) - 在每个循环末尾加入
await asyncio.sleep(0.1):这是实现并发的核心,它会让当前任务暂停,把控制权交还给事件循环,让其他任务有机会执行,同时也避免高频轮询消耗资源 - 将
self.files从列表改为集合,优化文件差集运算的效率,同时避免重复添加文件 - 优化了多文件新增/删除的处理逻辑(原来的代码只处理单个文件)
内容的提问来源于stack exchange,提问作者youjin1985
相关产品推荐
相关产品推荐

