This PEP introduces changes to Python’s mechanisms for raisingexceptions intended to reduce both line noise and the size of thelanguage.
One of Python’s guiding maxims is“there should be one – andpreferably only one – obvious way to do it”. Python 2.x’sraise statement violates this principle, permitting multipleways of expressing the same thought. For example, these statementsare equivalent:
raiseE,VraiseE(V)
There is a third form of theraise statement, allowing arbitrarytracebacks to be attached to an exception[1]:
raiseE,V,T
where T is a traceback. As specified inPEP 344,exception objects in Python 3.x will possess a__traceback__attribute, admitting this translation of the three-expressionraise statement:
raiseE,V,T
is translated to
e=E(V)e.__traceback__=Traisee
Using these translations, we can reduce theraise statement fromfour forms to two:
raise (with no arguments) is used to re-raise the activeexception in anexcept suite.raiseEXCEPTION is used to raise a new exception. This form hastwo sub-variants:EXCEPTION may be an exception class or aninstance of an exception class; valid exception classes areBaseException and its subclasses (PEP 352). IfEXCEPTIONis a subclass, it will be called with no arguments to obtainan exception instance.To raise anything else is an error.
There is a further, more tangible benefit to be obtained through thisconsolidation, as noted by A.M. Kuchling[2].
PEP8doesn't express any preference between thetwoformsofraisestatements:raiseValueError,'blah'raiseValueError("blah")Ilikethesecondformbetter,becauseiftheexceptionargumentsarelongorincludestringformatting,youdon't need to use linecontinuationcharactersbecauseofthecontainingparens.
The BDFL has concurred[3] and endorsed theconsolidation of the severalraise forms.
In Python 3, the grammar forraise statements will changefrom[1]
raise_stmt:'raise'[test[','test[','test]]]
to
raise_stmt:'raise'[test]
Because of its relation to exception raising, the signature for thethrow() method on generator objects will change, dropping theoptional second and third parameters. The signature thus changes (PEP 342)from
generator.throw(E,[V,[T]])
to
generator.throw(EXCEPTION)
WhereEXCEPTION is either a subclass ofBaseException or aninstance of a subclass ofBaseException.
In Python 2, the followingraise statement is legal
raise((E1,(E2,E3)),E4),V
The interpreter will take the tuple’s first element as the exceptiontype (recursively), making the above fully equivalent to
raiseE1,V
As of Python 3.0, support for raising tuples like this will bedropped. This change will bringraise statements into line withthethrow() method on generator objects, which already disallowsthis.
All two- and three-expressionraise statements will requiremodification, as will all two- and three-expressionthrow() callson generators. Fortunately, the translation from Python 2.x toPython 3.x in this case is simple and can be handled mechanicallyby Guido van Rossum’s 2to3 utility[4] using theraise andthrow fixers ([5],[6]).
The following translations will be performed:
raise statements will be leftintact.raise statements will be converted fromraiseE,V
to
raiseE(V)
Two-expressionthrow() calls will be converted from
generator.throw(E,V)
to
generator.throw(E(V))
See point #5 for a caveat to this transformation.
raise statements will be converted fromraiseE,V,T
to
e=E(V)e.__traceback__=Traisee
Three-expressionthrow() calls will be converted from
generator.throw(E,V,T)
to
e=E(V)e.__traceback__=Tgenerator.throw(e)
See point #5 for a caveat to this transformation.
raise statements whereE is atuple literal can be converted automatically using2to3’sraise fixer.raise statements whereE is a non-literaltuple, e.g., the result of a function call, will need to beconverted manually.raise statements whereE is anexception class andV is an exception instance will needspecial attention. These cases break down into two camps:raiseE,V as a long-hand version of the zero-argumentraise statement. As an example, assuming F is a subclassof Etry:something()exceptFasV:raiseF(V)exceptEasV:handle(V)
This would be better expressed as
try:something()exceptF:raiseexceptEasV:handle(V)
raiseE,V as a way of “casting” an exception to anotherclass. Taking an example fromdistutils.compiler.unixcompilertry:self.spawn(pp_args)exceptDistutilsExecErrorasmsg:raiseCompileError(msg)
This would be better expressed as
try:self.spawn(pp_args)exceptDistutilsExecErrorasmsg:raiseCompileErrorfrommsg
Using theraise...from... syntax introduced inPEP 344.
This PEP was implemented in revision 57783[7].
This document has been placed in the public domain.
Source:https://github.com/python/peps/blob/main/peps/pep-3109.rst
Last modified:2025-02-01 08:59:27 GMT