Skip to content Skip to sidebar Skip to footer

Reused Variable In Mako Template Cause "unboundlocalerror: Local Variable 'xyz' Referenced Before Assignment"

I have this 'funny' issue. I know this error message is found in a lot of places, but I couldn't find one explicitely related to Mako. In a Mako template, I have (snippet): <%in

Solution 1:

It is best to think of a Mako template as being similar to a piece of python code. Thus, as in python, you will have issues if you expect a variable to take on both local scope and global (or nested scope).

Thinking of a template as a function that takes variables, and defines within it various other functions including a body() function, then your problem is effectively similar to the following

>>>deff(x):...defbody():...print x...for x inrange(5):...print x...    body()...>>>f(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in f
  File "<stdin>", line 3, in body
UnboundLocalError: local variable 'x' referenced before assignment

You shouldn't expect this to work in Python, and similarly, you shouldn't expect it to work in a Mako template.

Solution 2:

I think you need to include label in my_method arguments.

<%def name="my_method(label)">Search for${label}</%def>
[...]
<h2>${label.capitalize()} found: ${len(l)}</h2>
...
<ol>
% for (label, field_name) in some_list:
    <li>${label}: ${field_name}</li>
% endfor
</ol>

Follow-up

As far as I can tell you'll have to change the loop variable name. It may be a nuance of Mako or Python namespaces that I don't completely understand, but this appears to be the safest option. In my opinion reusing variable names like this is bad form anyway and leads to unexpected behaviour, is error prone, etc.

It appears from my evaluation that this may be a feature of mako in the way it handles namespaces. Consider the following examples. The first raises the same UnboundLocalError exception. The second is identical in structure and does not raise exception.

Example 1 raises UnboundLocalError:

from mako.template import Template

src = """
Text in "label": ${label}
Elements of "some_list": ${some_list}

Labels and names in "some_list"
% for (label,name) in some_list:
    label: name -> ${label}: ${name}
% endfor

${label.capitalize()}
"""

my_template = Template(src)

s = [('foo', 'bar'), ('spam', 'eggs')]
data = {'label': 'bogus', 'some_list':s, 'l':[1, 2, 3, 4]}

print(my_template.render(**data))

Outputs:

    Traceback (most recent call last):

      ...

      File "C:\Python26\ArcGIS10.0\Lib\site-packages\mako-0.6.2-py2.6.egg\mako\runtime.py", line 704, in _exec_template
        callable_(context, *args, **kwargs)
      File "memory:0xb5b6b0", line 22, in render_body
    UnboundLocalError: local variable 'label' referenced before assignment

Example 2 evaluates successfully:

from mako.template import Template

src = """
Text in "label": ${label}
Elements of "some_list": ${some_list}

Labels and names in "some_list"
% for (loop_label,name) in some_list:
    label: name -> ${loop_label}: ${name}
% endfor

${label.capitalize()}
"""

my_template = Template(src)

s = [('foo', 'bar'), ('spam', 'eggs')]
data = {'label': 'bogus', 'some_list':s, 'l':[1, 2, 3, 4]}

print(my_template.render(**data))

Output:

    Text in "label": eggs
    Elements of "some_list": [('foo', 'bar'), ('spam', 'eggs')]

    Labels and names in "some_list"
        label: name -> foo: bar
        label: name -> spam: eggs

    Eggs

To demonstrate that Mako is not evaluating the template as you might expect, here is a similarly structured pure Python example that evaluates just fine.

src = """
print('Text in "label": %s' % label)
print('Elements of "some_list": %s' % some_list)

print('')
print('Labels and names in "some_list"')
for (label,name) in some_list:
    print('    label: name -> %s:%s' % (label, name))

print('')
print('Caps "label": %s' % label.capitalize())
"""

code = compile(src, 'None', 'exec')

s = [('foo', 'bar'), ('spam', 'eggs')]
data = {'label': 'bogus', 'some_list':s, 'l':[1, 2, 3, 4]}

eval(code, {}, data)

Outputs:

    Text in "label": bogus
    Elements of "some_list": [('foo', 'bar'), ('spam', 'eggs')]

    Labels and names in "some_list"
        label: name -> foo:bar
        label: name -> spam:eggs

    Caps "label": Spam

Post a Comment for "Reused Variable In Mako Template Cause "unboundlocalerror: Local Variable 'xyz' Referenced Before Assignment""