Thursday, June 26, 2025¶
I was wondering… yes there is a pitfall when using Jinja. When your class defines a property, and when, while computing this property, it raises an AttributeError, then Jinja catches this exception and reports that your object doesn’t have the requested property instead of showing the full traceback.
from jinja2 import Environment, DictLoader
A = False
B = True
class Foo:
_bar = None
@property
def bar(self):
if self._bar is None:
self._bar = Answer(self)
return self._bar
class Answer:
def __init__(self, foo):
if A:
raise Exception("Oops")
elif B:
raise AttributeError("Oops")
self.answer = 42
TEMPLATE = "The answer is {{foo.bar.answer}}."
env = Environment(
loader=DictLoader({'1': TEMPLATE}),
)
tpl = env.get_template('1')
print(tpl.render(foo=Foo()))
Output when there’s no bug:
The answer is 42.
Output with exception of type A:
Traceback (most recent call last):
File "/home/luc/work/blog/docs/blog/2025/0626.py", line 35, in <module>
print(tpl.render(foo=Foo()))
^^^^^^^^^^^^^^^^^^^^^
File "/home/luc/venvs/dev/lib/python3.12/site-packages/jinja2/environment.py", line 1295, in render
self.environment.handle_exception()
File "/home/luc/venvs/dev/lib/python3.12/site-packages/jinja2/environment.py", line 942, in handle_exception
raise rewrite_traceback_stack(source=source)
File "<template>", line 1, in top-level template code
File "/home/luc/venvs/dev/lib/python3.12/site-packages/jinja2/environment.py", line 490, in getattr
return getattr(obj, attribute)
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/luc/work/blog/docs/blog/2025/0626.py", line 14, in bar
self._bar = Answer(self)
^^^^^^^^^^^^
File "/home/luc/work/blog/docs/blog/2025/0626.py", line 22, in __init__
raise Exception("Oops")
Exception: Oops
Output with exception of type B:
Traceback (most recent call last):
File "/home/luc/work/blog/docs/blog/2025/0626.py", line 35, in <module>
print(tpl.render(foo=Foo()))
^^^^^^^^^^^^^^^^^^^^^
File "/home/luc/venvs/dev/lib/python3.12/site-packages/jinja2/environment.py", line 1295, in render
self.environment.handle_exception()
File "/home/luc/venvs/dev/lib/python3.12/site-packages/jinja2/environment.py", line 942, in handle_exception
raise rewrite_traceback_stack(source=source)
File "<template>", line 1, in top-level template code
File "/home/luc/venvs/dev/lib/python3.12/site-packages/jinja2/environment.py", line 490, in getattr
return getattr(obj, attribute)
^^^^^^^^^^^^^^^^^^^^^^^
jinja2.exceptions.UndefinedError: '__main__.Foo object' has no attribute 'bar'