为何Python中sys.exit输出有时早于print?生成器代码输出顺序异常
生成器迭代中输出顺序颠倒的原因
多次运行下述Python代码时,有时能得到预期输出,但有时由StopIteration异常触发的“End of list”会先输出,之后才显示循环中print语句的内容。预期每次输出都应是“End of list”在最后,因为该异常应在生成器无元素可迭代后触发,但实际约半数情况出现输出顺序颠倒。
import sys data = ['a', 'b', 'c'] def myf(*args): for arg in args: yield arg generator_object = myf(*data) while True: try: print(next(generator_object)) except StopIteration: sys.exit('End of list')
实际异常输出示例:
End of list a b c Process finished with exit code 1
原因分析
这是因为标准输出(print默认使用的stdout流)和标准错误流(sys.exit提示信息输出的stderr流)是两个独立的输出通道,二者的缓冲区刷新机制不同:
print输出到stdout,默认采用行缓冲模式,只有遇到换行符、缓冲区满或者程序正常退出时,才会将缓冲区内容写入终端。sys.exit()的提示信息直接输出到stderr,该流通常是无缓冲或立即刷新的,内容会直接显示在终端。
当程序运行时,stdout中的a、b、c可能还停留在缓冲区未输出,而stderr的“End of list”已经被即时打印。等到程序退出时,stdout的缓冲区才被强制刷新,导致原本应先出现的内容后显示,造成顺序颠倒。
如果要解决这个问题,有两种简单方法:
- 让
print强制刷新缓冲区:修改为print(next(generator_object), flush=True) - 将
sys.exit的提示信息转到stdout输出:替换为print('End of list'); sys.exit()
内容的提问来源于stack exchange,提问作者Manuel
相关产品推荐
相关产品推荐

