Question: In the process of developing a custom Jinja2 extension (a tag, not a filter), I am finding myself in the situation where I need to extract a list of first-level keys that refer to the runtime values saved in a namespace. Individual first-level values with known keys are easy to extract from the namespace with a simple Getattr(Name('my_ns_name', 'load'), 'my_key', 'load') node. But how can I get the list of all first-level keys when not known in advance? I inspected Namespace objects as returned at runtime by a Name('my_ns_name', 'load') node and haven't found any relevant information there. I also feel that the NSRef node type could possibly be a key to the solution, but I still fail to understand its purpose, specially considering how little documented it is. I also thought of using a For node and iterate through some collection returned by one of the nodes.iter_* functions, but that doesn't seem to apply to namespace attributes. So I'm a bit stuck, now... Here's a condensed version of my attempts so far: import pprint from jinja2 import nodes from jinja2.ext import Extension class InspectExtension(Extension): tags = {"inspect"} def __init__(self, environment): super().__init__(environment) def parse(self, parser): lineno = parser.stream.expect("name:inspect").lineno expr = parser.parse_expression() context = nodes.DerivedContextReference() return nodes.Output([ nodes.Const(expr), # Inspect the AST nodes.TemplateData('\n'), # For a nicer output self.call_method("_render", [expr, context]) # Runtime inspection ]).set_lineno(lineno) def _render(self, value, context): result = { "class": value.__class__.__name__, "attrs": dir(value), "context": list(context.get_all().keys()) } return pprint.pformat(result, compact=False) inspect = InspectExtension  With this template: <!DOCTYPE html> <html><body><pre> {% set ns = namespace() %} {% set ns.test = 'foobar' %} {{ ns.test }} {% inspect ns %} </pre></body></html>  Outputs (rendered HTML): foobar Getattr(node=Name(name='ns', ctx='load'), attr='test', ctx='load') {'attrs': ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'], 'class': 'Namespace', 'context': ['range', 'dict', 'lipsum', 'cycler', 'joiner', 'namespace', 'environ', 'get_context', 'request', 'result', 'ctx', 'ns'], 'value': }  For completeness:  The extension source code is located in ./j2_ext/inspect.py, along with the customary __init__.py which contains a single statement from .inspect import inspect. Jinja2 engine is called through jinja2-cli, passing the extension name to the --extension argument, as such:  jinja2 --format=json --extension=.j2_ext.inspect /path/to/my_tpl.j2 < my_data.json  Some relevant documentation:  Official Jinja2 documentation: https://jinja.palletsprojects.com/en/stable/extensions/#extension-api Examples of Jinja2 extensions: https://github.com/topics/jinja2-extension?o=asc&s=stars 

Answer: If you read the source code you'll find that the attributes of jinja2.utils.Namespace are stored in the __attrs attribute, a "private" variable prefixed with double underscores that is subject to name mangling, so you would have to access it with the _Namespace prefix instead. So to obtain a list of all first-level keys stored in the namespace value, evaluate: list(value._Namespace__attrs)