Python3.4.3中用create_subprocess_exec调用无限进程遇异常忽略问题
解决Python 3.4.3 asyncio中取消tail -f子进程时的异常问题
我来帮你搞定这个问题,你遇到的Exception ignored in:异常,本质是tailf协程被取消时没有正确终止子进程,或者异常处理逻辑不完整导致的。当asyncio取消任务时会抛出CancelledError,如果没妥善处理这个异常并清理子进程资源,就会引发残留进程相关的忽略异常。
问题分析
你的原代码里,except BaseException ...的处理不完整:
- 没有明确捕获
CancelledError并终止tail子进程 - 子进程如果没有被主动终止,即便协程被取消,它还会继续运行,进而导致后续的异常提示
修正后的解决方案
下面是完整的可运行代码,我会详细标注关键修复点:
import asyncio import time @asyncio.coroutine def tailf(): proc = None try: create = asyncio.create_subprocess_exec( 'tail', '-f', '/tmp/file', stdout=asyncio.subprocess.PIPE, ) proc = yield from create while True: # 读取行时也可能被取消,所以这里要处理CancelledError line = yield from proc.stdout.readline() if not line: break # 子进程退出时readline返回空 print(line.decode('utf-8').strip()) except asyncio.CancelledError: # 当协程被取消时,主动终止子进程 if proc is not None and proc.returncode is None: proc.terminate() # 等待子进程结束(可选,确保资源完全释放) yield from proc.wait() # 重新抛出异常,让asyncio知道任务已被取消 raise except BaseException as e: print(f"tailf出现异常: {e}") # 如果子进程还在运行,也要终止 if proc is not None and proc.returncode is None: proc.terminate() yield from proc.wait() @asyncio.coroutine def other_task(): # 模拟其他耗时任务,运行5秒后完成 print("其他任务开始运行...") yield from asyncio.sleep(5) print("其他任务完成") def main(): loop = asyncio.get_event_loop() # 创建tailf任务 tail_task = asyncio.ensure_future(tailf()) # 创建其他任务 other_future = asyncio.ensure_future(other_task()) # 等待其他任务完成 loop.run_until_complete(other_future) # 取消tail任务并等待它结束 print("准备取消tail任务...") tail_task.cancel() try: loop.run_until_complete(tail_task) except asyncio.CancelledError: # 这里捕获是正常的,因为我们主动取消了任务 print("tail任务已被取消并结束") # 关闭事件循环 loop.close() print("事件循环已关闭") if __name__ == "__main__": main()
关键修复说明
- 捕获
CancelledError并终止子进程:当tailf任务被取消时,先检查子进程是否还在运行,调用proc.terminate()终止它,再用proc.wait()等待它完全退出,避免残留进程。 - 重新抛出
CancelledError:这一步是必须的,让asyncio框架正确识别任务已被取消,避免后续的异常提示。 - 处理
readline()的取消场景:yield from proc.stdout.readline()在等待输入时也可能被取消,所以外层的异常捕获能覆盖这个情况。 - 完整的异常清理逻辑:在
BaseException块里也加入子进程终止逻辑,确保任何异常情况下都能清理资源。
这样修改后,当其他任务完成后,tail子进程会被优雅终止,协程也能正常退出,不会再出现Exception ignored in:的异常提示。
内容的提问来源于stack exchange,提问作者Vadim Pushtaev
相关产品推荐
相关产品推荐

