Scope of variables in a For loop

What is the scope of variables in a for loop?

I have read here http://jinja.pocoo.org/docs/dev/templates/#loop-controls that variables in a with loop are explicitly, ‘not visible outside of the scope’, but nothing is mentioned about variables in a for loop.

So why doesn’t this work as I expect it to? i.e. why doesn’t lowest show the lowest value of item.state at the end?

{% set lowest = states('sensor.latest_tasmota_version')[1:] %}

lowest before for loop is {{ lowest }}

{%- for item in states
     if item.entity_id.split(".")[1].startswith('sonoff') and 
        item.entity_id.split(".")[1].endswith('firmware') and
        item.state != 'unknown' %}

      {% if item.state < lowest %}
        {% set lowest = item.state -%}
        lowest is {{ lowest }}
      {% endif %}

{%- endfor %}

lowest after for loop is {{ lowest }} 

1 Like

In the for loop documentation (you have to scroll a bit to find it) it says:

Please note that assignments in loops will be cleared at the end of the iteration and cannot outlive the loop scope. Older versions of Jinja2 had a bug where in some circumstances it appeared that assignments would work. This is not supported. See Assignments for more information about how to deal with this.

1 Like

Fantastic. Thanks for the pointer.
I have it working now!

Post your working code and mark either it or @pnbruckner 's reply as a solution. I have a feeling you won’t be the only one to hit this snag and a visual example is always a better learning tool than the docs :slight_smile:

EDIT: Following on from the post that follows this one from @pnbruckner I have edited this one to add the line

    entity_id: sensor.time

to the template sensor.

For anyone coming along reading this with the same issue I had, this post now contains a fully working solution. Ignore where it says ‘But in HA it doesn’t…’ It now works perfectly as given in this post.

=========================

@anon43302295 Yes absolutely, I couldn’t agree more and planned to do that this morning after getting it fully set up in my config. That response to @pnbruckner was posted after quick testing in the config tool last night which now appears to have been a bit premature…

So,

In the templating tool this works perfectly (screen capture below)

      {% set ns = namespace(lowest = states('sensor.tasmota_current_version')[1:]) %}
      {% for item in states if item.entity_id.split(".")[1].endswith('firmware') and 
                               item.entity_id.split(".")[1].startswith('sonoff') and 
                               item.state != 'unknown' and
                               item.state < ns.lowest %}
        {% set ns.lowest= item.state %}
      {% endfor %}
      v{{ ns.lowest }}  

But in HA it doesn’t. It still returns the original value as set up outside the for loop.

  • Here are my sensors:

    # Latest Sonoff Tasmota firmware version
    - platform: command_line
      name: Tasmota Current Version
      command: "curl -s https://github.com/arendst/Sonoff-Tasmota/releases/latest | cut -d'\"' -f2 | rev | cut -d'/' -f1 | rev"
      scan_interval: 86400
    
    
    # Earliest Sonoff Tasmota firmware version
    - platform: template
      sensors:
        tasmota_earliest_installed_version:
          entity_id: sensor.time
          friendly_name: Tasmota Earliest Installed Version
          value_template: >
            {% set ns = namespace(lowest = states('sensor.tasmota_current_version')[1:]) %}
            {% for item in states if item.entity_id.split(".")[1].endswith('firmware') and 
                                     item.entity_id.split(".")[1].startswith('sonoff') and 
                                     item.state != 'unknown' and
                                     item.state < ns.lowest %}
              {% set ns.lowest= item.state %}
            {% endfor %}
            v{{ ns.lowest }}  
    
    
    # Installed firmware version
    - platform: mqtt
      name: "Sonoff01_firmware"
      state_topic: "stat/sonoff01/STATUS2"
      value_template: "{{ value_json.StatusFWR.Version }}"
    
    - platform: mqtt
      name: "Sonoff02_firmware"
      state_topic: "stat/sonoff02/STATUS2"
      value_template: "{{ value_json.StatusFWR.Version }}"
    
    ...and so on for every Sonoff device
    
  • Result as displayed in Lovelace

image

  • For completeness here are the entities as defined in Lovelace

                - entity: sensor.tasmota_current_version
                  name: Tasmota Current Version
                - entity: sensor.tasmota_earliest_installed_version
                  name: Tasmota Earliest Installed Version
    
  • And here is the screenshot of templating tool showing correct output

1 Like

I think you’ve been bit by the new classic template sensor problem. The automatic entity_id parsing for sensor.tasmota_earliest_installed_version is only finding sensor.tasmota_current_version, so it will only update at startup, and then only when sensor.tasmota_current_version changes. However, it looks like you also want it to update whenever other entities (i.e., ones whose object_id starts with “sonoff” and ends with “firmware”) update. So you either have to manually list all the entity_id’s the template sensor needs to watch, or you need to get it to update often (such as manually listing sensor.time.)

And I think I’ve been helped by the classic HA Forum community.

Thanks it is working perfectly now. I will edit my previous post for anyone coming here later.