builtins.TypeError: catching classes that do not inherit from BaseException is not allowed

hongy...@gmail.com hongyi.zhao at gmail.com
Thu Dec 30 08:14:17 EST 2021


On Thursday, December 30, 2021 at 9:04:36 PM UTC+8, hongy... at gmail.com wrote:
> I try to compute the factorial of a large number with tail-recursion optimization decorator in Python3. The following code snippet is converted from the code snippet given here [1] by the following steps: 
> 
> $ pyenv shell datasci 
> $ python --version 
> Python 3.9.1 
> $ pip install 2to3 
> $ 2to3 -w this-script.py 
> 
> ``` 
> # This program shows off a python decorator( 
> # which implements tail call optimization. It 
> # does this by throwing an exception if it is 
> # its own grandparent, and catching such 
> # exceptions to recall the stack. 
> 
> import sys 
> 
> class TailRecurseException: 
> def __init__(self, args, kwargs): 
> self.args = args 
> self.kwargs = kwargs 
> 
> def tail_call_optimized(g): 
> """ 
> This function decorates a function with tail call 
> optimization. It does this by throwing an exception 
> if it is its own grandparent, and catching such 
> exceptions to fake the tail call optimization. 
> 
> This function fails if the decorated 
> function recurses in a non-tail context. 
> """ 
> def func(*args, **kwargs): 
> f = sys._getframe() 
> if f.f_back and f.f_back.f_back \ 
> and f.f_back.f_back.f_code == f.f_code: 
> raise TailRecurseException(args, kwargs) 
> else: 
> while 1: 
> try: 
> return g(*args, **kwargs) 
> except TailRecurseException as e: 
> args = e.args 
> kwargs = e.kwargs 
> func.__doc__ = g.__doc__ 
> return func 
> 
> @tail_call_optimized 
> def factorial(n, acc=1): 
> "calculate a factorial" 
> if n == 0: 
> return acc 
> return factorial(n-1, n*acc) 
> 
> print(factorial(10000)) 
> # prints a big, big number, 
> # but doesn't hit the recursion limit. 
> 
> @tail_call_optimized 
> def fib(i, current = 0, next = 1): 
> if i == 0: 
> return current 
> else: 
> return fib(i - 1, next, current + next) 
> 
> print(fib(10000)) 
> # also prints a big number, 
> # but doesn't hit the recursion limit. 
> ``` 
> However, when I try to test the above script, the following error will be triggered: 
> ``` 
> $ python this-script.py 
> Traceback (most recent call last): 
> File "/home/werner/this-script.py", line 32, in func 
> return g(*args, **kwargs) 
> File "/home/werner/this-script.py", line 44, in factorial 
> return factorial(n-1, n*acc) 
> File "/home/werner/this-script.py", line 28, in func 
> raise TailRecurseException(args, kwargs) 
> TypeError: exceptions must derive from BaseException 
> 
> During handling of the above exception, another exception occurred: 
> 
> Traceback (most recent call last): 
> File "/home/werner/this-script.py", line 46, in <module> 
> print(factorial(10000)) 
> File "/home/werner/this-script.py", line 33, in func 
> except TailRecurseException as e: 
> TypeError: catching classes that do not inherit from BaseException is not allowed 
> ``` 
> 
> Any hints for fixing this problem will be highly appreciated. 

See here [1] for the related discussion. 

[1] https://discuss.python.org/t/typeerror-catching-classes-that-do-not-inherit-from-baseexception-is-not-allowed/12800

HZ


More information about the Python-list mailing list