0

I have a module that I use as a decorator - to modify a function that I use recursively.

The module optimises a tail call to avoid recursion limit - see credits below.

If I copy paste the code on the console, first the module and then the decorated function, it works ok.

But if I import the module, I got error that module fails to import sys - despite I import it in the first line in my module.

    Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "TailRecurseException.py", line 18, in func
    f = sys._getframe()
NameError: global name 'sys' is not defined
>>> 

I thought I am importing the module in a wrong way:

I tried with

from TailRecurseException import tail_call_optimized

and

from TailRecurseException import *

@tail_call_optimized
def recursive_activations( ...)

but same results.

What can I do wrong in the module to decorate another function, since it fails to import sys?


This is my submodule:

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 it's 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, e:
          args = e.args
          kwargs = e.kwargs
  func.__doc__ = g.__doc__
  return func

Credits: https://mail.python.org/pipermail//python-list/2006-February/407243.html

user305883
  • 1,635
  • 2
  • 24
  • 48
  • Are you sure the code you're running is the same as what you're showing us? The exception says that the name `sys` is not accessible, which wouldn't happen if the `import sys` line ran at the top of the module. Make sure you're not running an older version of your code (or give an updated traceback if the exception has changed). – Blckknght Jul 17 '18 at 07:46
  • Cannot reproduce, neither in Python 2.7, nor in Python 3 after syntax fixes. What version are you using exactly? And please give a [mcve] exhibiting the problem. – Serge Ballesta Jul 17 '18 at 08:39
  • Hi, sure I'm running what I'm showing you. May it be due to some configuration in virtual environment ? Using version 2.7 in virtual env. – user305883 Jul 20 '18 at 15:07

1 Answers1

0

If I copy-paste the submodule code you've attached to tcr.py, then do

from tcr import tail_call_optimized

@tail_call_optimized
def recursive_activations(x):
    pass

everything works just fine.

(As an aside, you'll want to change that except TailRecurseException, e: to except TailRecurseException as e: to conform to modern Python.)

AKX
  • 152,115
  • 15
  • 115
  • 172