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:04:24 EST 2021


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.

[1]  https://stackoverflow.com/q/27417874

Regards,
HZ


More information about the Python-list mailing list