# (Python API question) Recursively expanding Ansible host vars from a standalone Python script

**URL:** <https://forum.ansible.com/t/python-api-question-recursively-expanding-ansible-host-vars-from-a-standalone-python-script/36178>\
**Category:** Ansible Project\
**Created:** [January 5, 2022, 8:53pm UTC](https://forum.ansible.com/t/python-api-question-recursively-expanding-ansible-host-vars-from-a-standalone-python-script/36178 "2022-01-05T20:53:30Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![arviasf](https://avatars.discourse-cdn.com/v4/letter/a/a8b319/32.png) [@arviasf](https://forum.ansible.com/u/arviasf)\
**Post date:** [January 5, 2022, 8:53pm UTC](https://forum.ansible.com/t/python-api-question-recursively-expanding-ansible-host-vars-from-a-standalone-python-script/36178/1 "2022-01-05T20:53:30Z")

</div>

Hi folks - In a standalone Python script, I need to enumerate and expand all host variables from a given Ansible inventory file. In this inventory file, there are variables which reference other variables using Jinja2 templates, and the level of recursion in those can be 3-4 levels deep. Some of the vars use Jinja2 tests (such as the version (version\_compare) test) within their templates.

After some experimentation I could combine Ansible libraries with Jinja2 to do this. But it looks like a lot of work. Is there an intrinsic way to use ansible Python API and recursively expand all host variables?

FYI, here is what currently works for me:

from ansible.parsing.dataloader import DataLoader  
from ansible.inventory.manager import InventoryManager  
from ansible.vars.manager import VariableManager  
from ansible.plugins.test.core import version\_compare  
from jinja2 import Template, Environment

sources = [‘/project/ansible/conf/hosts’]  
loader = DataLoader()  
inventory = InventoryManager(loader=loader, sources=sources)  
variable\_manager = VariableManager(loader=loader, inventory=inventory)

myhost = inventory.get\_hosts()[0]  
vars = variable\_manager.get\_vars(host = myhost)

environment = Environment()  
environment.tests[“version”] = version\_compare

for k, v in vars.items():  
if type(v) == str:  
expanded\_value = environment.from\_string(v)

while True:  
expanded\_value = expanded\_value.render(vars)  
if “{{” not in expanded\_value:  
break  
else:  
expanded\_value = environment.from\_string(expanded\_value)

print(k, “:”, expanded\_value)

---

<div class="post-metadata">

**Author:** ![sivel](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/sivel/32/1198_2.png) [@sivel](https://forum.ansible.com/u/sivel)\
**Post date:** [January 5, 2022, 8:57pm UTC](https://forum.ansible.com/t/python-api-question-recursively-expanding-ansible-host-vars-from-a-standalone-python-script/36178/2 "2022-01-05T20:57:21Z")

</div>

Since you are already importing things from ansible, I’d recommend you import Templar, and use that instead of directly using jinja2. Templar already has this functionality.

---

<div class="post-metadata">

**Author:** ![Dick\_Visser](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Dick\_Visser](https://forum.ansible.com/u/Dick_Visser)\
**Post date:** [January 5, 2022, 9:14pm UTC](https://forum.ansible.com/t/python-api-question-recursively-expanding-ansible-host-vars-from-a-standalone-python-script/36178/3 "2022-01-05T21:14:15Z")

</div>

I’m interested in this as well, if possible please post any results

---

<div class="post-metadata">

**Author:** ![arviasf](https://avatars.discourse-cdn.com/v4/letter/a/a8b319/32.png) [@arviasf](https://forum.ansible.com/u/arviasf)\
**Post date:** [January 6, 2022, 12:18am UTC](https://forum.ansible.com/t/python-api-question-recursively-expanding-ansible-host-vars-from-a-standalone-python-script/36178/4 "2022-01-06T00:18:49Z")

</div>

Thank you for the suggestion re: Templar. I was able to accomplish the needed functionality with this code:

from ansible.parsing.dataloader import DataLoader  
from ansible.inventory.manager import InventoryManager  
from ansible.vars.manager import VariableManager  
from ansible.template import Templar

sources = [‘/project/ansible/conf/hosts’]  
loader = DataLoader()  
inventory = InventoryManager(loader=loader, sources=sources)  
variable\_manager = VariableManager(loader=loader, inventory=inventory)

myhost = inventory.get\_hosts()[0]  
vars = variable\_manager.get\_vars(host = myhost)

templar = Templar(loader= loader, variables=vars)

for k, v in vars.items():  
if type(v) == str:  
expanded\_value = templar.template(v)  
print(k, “:”, expanded\_value)

---

<div class="post-metadata">

**Author:** ![Vincent\_Rubiolo](https://avatars.discourse-cdn.com/v4/letter/v/a183cd/32.png) [@Vincent\_Rubiolo](https://forum.ansible.com/u/Vincent_Rubiolo)\
**Post date:** [January 6, 2022, 9:18pm UTC](https://forum.ansible.com/t/python-api-question-recursively-expanding-ansible-host-vars-from-a-standalone-python-script/36178/5 "2022-01-06T21:18:01Z")

</div>

Hi there,

I have a very similar problem using ansible-inventory which does not perform this expansion either and this is causing me issues with AWX (see [https://groups.google.com/g/awx-project/c/uW2jyvqA9MY](https://groups.google.com/g/awx-project/c/uW2jyvqA9MY) for more information).

Your code opens up new possibilities for me as I could use it as a base to write a custom inventory plugin which I think could perform this expansion using the extra variables specified via --extra-vars (my inventory variables reference those extra vars via Jinja templates and do not currently get expanded).

Thanks a lot for sharing !

Vincent
