How come StopIteration.__base__ is not BaseException?

Steven D'Aprano steve at pearwood.info
Tue Aug 27 05:22:01 EDT 2013


On Tue, 27 Aug 2013 08:17:15 +0200, Marco Buttu wrote:

> On 08/26/2013 10:10 PM, random832 at fastmail.us wrote:
> 
>> The reason KeyboardInterrupt and SystemExit inherit from BaseException
>> is because you often want them to escape (allowing the program to quit)
>> from code that would otherwise catch them (by catching Exception). On
>> the contrary, StopIteration is almost always used in a context that
>> catches it specifically.
> 
> But if I want to catch it specifically (except BaseIteration), why

You mean StopIteration.

> doesn't it hinerit directly from BaseException? It's not an error and
> it's not a warning. I would like to see a piece of code in which it is
> useful to catch it generically with a except Exception clause instead of
> an except StopIteration...

You are focused on the wrong thing. It doesn't matter that we normally 
catch StopIteration specifically. We normally catch *all* exceptions 
specifically. 

try: 
    ...
except ValueError:
    ...

This doesn't mean that ValueError should inherit from BaseException. So 
the fact that we catch StopIteration specifically too doesn't mean it 
needs to inherit from BaseException.

What matters is that when you catch "nearly everything", StopIteration is 
included in the "nearly everything", but SysExit and KeyboardInterrupt 
should not be. Consider:


try:
    main()
except Exception as e:
    print('an unexpected error occurred')
    log_unhandled_exception(e)
    emergency_shutdown()
    sys.exit(1)
except (KeyboardInterrupt, SysExit):
    # User wants to exit.
    clean_exit()
    sys.exit(0)



Which except clause would you expect an unhandled StopIteration to fall 
under? The unexpected error clause, or the "user wants to exit cleanly" 
clause?



-- 
Steven



More information about the Python-list mailing list