Reused Variable In Mako Template Cause "unboundlocalerror: Local Variable 'xyz' Referenced Before Assignment"
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""