How to prevent running python_script if already running

Tags: #<Tag:0x00007f78174551a0> #<Tag:0x00007f7817454e08>

HI,

Based on various triggers, I run a python script, to give me an overview of the triggering entities and their states. I do so for switches, lights, device_trckers, media_players, and some active threshold sensors.

they all end with:

  action:
    - delay:
        seconds: 2
    - service: python_script.summary

In a calm period in the HA system, this is no problem, but I suspect it to become an issue when several of the triggered automations pass their conditions, and run the action… with the possibility of simultaneous called actions. Which is no good of course.

Can we somehow test if a python_script is currently being run, and add that as a condition to the automations?
thanks for having a look.

I don’t think so. But you could use an input_boolean as an intermediary. In the automations where you normally call python_script.summary, instead turn on an input_boolean. Then add one automation that is triggered by that entity changing to 'on'. Then add at the end of python_script.summary a service call to turn the input_boolean off. That should protect the script from running more than once at the same time.

1 Like

yes! that is very clever and simple. thank you very much!

- alias: 'Run Summary'
  id: 'Run Summary'
  trigger:
    platform: state
    entity_id: input_boolean.run_summary
    to: 'on'
  condition: []
  action:
    - service: python_script.summary
    - delay: # give it some breathing time 
        seconds: 2
    - service: input_boolean.turn_off
      entity_id: input_boolean.run_summary

would it be useful/necessary to add a condition in the triggering automations on the boolean being ‘off’, like this:

- alias: 'Sense Hubs change'
  id: 'Sense Hubs change'
  trigger:
    platform: state
    entity_id:
      - binary_sensor.hassio_mqtt
      - binary_sensor.hassio_rpi4
      - binary_sensor.asus_router
      - binary_sensor.iungo
      - binary_sensor.solaredge
      - binary_sensor.synology
      - binary_sensor.timecapsule
      - binary_sensor.ikea_tradfri
      - binary_sensor.philips_hue
      - binary_sensor.kantoor_thermostat
  condition:
    - condition: template
      value_template: >
          {{is_state('input_boolean.run_summary','off')}}
    - condition: template
      value_template: >
          {{trigger.to_state.state in ['on','off'] }}
    - condition: template
      value_template: >
        {{trigger.to_state.state is not none and
          trigger.from_state.state is not none and
          trigger.to_state.state != trigger.from_state.state}}
  action:
    - delay:
        seconds: 1
#    - service: python_script.summary
    - service: input_boolean.turn_on
      entity_id: input_boolean.run_summary

I don’t think you understood what I was suggesting.

In your automations, instead of calling the python_script.summary, JUST turn the input_boolean on.

Then add this automation:

- trigger:
  - platform: state
    entity_id: input_boolean.summary
    to: 'on'
  action:
  - service: python_script.summary

Then at the end of summary.py add this:

hass.services.call(
    "input_boolean",
    "turn_off",
    {"entity_id": "input_boolean.summary"},
)

yes, that is working perfectly, I did understand that…same for the service: python_script.summary. so far so good.

I did not understand you meant to add the boolean turn_off directly in the python_script. Never thought of that, sorry. Thats why I added that to the regular automation I posted above.

Is there an advantage of doing it directly in the python_script?

Oh, ok. I guess I got confused by the part that turned the input boolean off after calling the script. I hadn’t expected that.

No, not needed or particularly useful.

Also, when checking if a binary entity is on, why do that in a template? A state condition would be simpler and more direct/efficient.

Well, in most cases it probably doesn’t matter. However, if a service ever takes longer than 10 seconds, the service call will return (while the service continues), so it’s more robust to turn the input boolean off at the end of the script. That way when it goes off you know the script is done.

moved all of those (have split up the larger summary.py into several smaller ones…) to their respective python_scripts.

I do see it as a big advantage in knowing for sure the python script has finished, opposed to the probably too quick turning_off when using the service in the automation. So, great tip, thanks!

I would have thought it to be useful, because the automation gets triggered by all triggering entities, and possibly more than one would like/the system can handle. Having a condition for the input_boolean being off, would prevent the action block from being invoked.

Not really sure why you say this. I have the automations trigger on state? Or, do you mean the condition in the automation:

  condition:
    - condition: template
      value_template: >
        {{is_state('input_boolean.run_summary','off')}}

are you saying

  condition:
    - condition: state
      entity_id: input_boolean.run_summary
      state: 'off'

is more efficient and uses less resources? I have the throughout my system, mainly because this can be checked in the developer-tools/template easily… Will have to rewrite 150+ automations if you tell me I would gain system resources…

If the trigger is:

- trigger:
  - platform: state
    entity_id: input_boolean.xyz
    to: 'on'

It will only trigger when it changes to 'on', not when something tries to turn it on when it’s already on. That’s the whole point of using the input_boolean in the first place. It will only cause the python_script to run when something turns it on. All the other automations that try to turn the input_boolean on when it’s already on will have no effect on the python_script. It’s acting kind of like a filter.

Regarding the template condition vs a state condition, why would you think rendering a template is faster / more efficient than simply checking the state of an entity?

Phil, I understand that, but I think we’re not talking about the same automation…

I thought you referred to the Sense Hubs Change automation (above), which is the automation I have placed the extra condition in, to check if the input_boolean.xyz is ‘off’. I would have thought that to be useful, because all of these entities can trigger the automation individually. Having it action only when boolean is off, would take out these.
In the above automation it might nit be very necessary, but in my lights (hue lights go unavailable all the time…), switches, media-trackers, and activity sensors, frequent triggers are to be expected. Calming that down with the extra condition would then ease up on the Ha core.

I don’t… I thought that’s what you implied when you said:

Ok, sorry, didn’t understand at first. Still, I think it’s six of one, half a dozen of the other. You’re either having it check a state or having it call a service which has no effect. If you want to get down to microseconds, then maybe. But to me, it’s cleaner to have fewer conditions. Sure, if there was some sort of side effect to turning something on that’s already on, then it would make sense to add the condition. But in this case, it absolutely has no side effect, and therefore, I’d opt for leaving out an unnecessary condition. But it’s a question of style more than anything else.

Regarding the state vs template condition, I think you interpreted what I said backwards. I clearly implied, no simply stated, that a state condition would be more efficient. But, again, efficiency is not the important point. If using a template condition comes more natural to you, or seems cleaner, than by all means. But you implied you’d want to do things the more efficient way, even if it meant rewriting 150+ automations.

Tbh, I seem to be forced to go looking for these micro seconds, because the Hue integration goes unavailable all the time when system internals prevent the correct timings between HA and the Hue hub.
Thats why I thought even better than trying to turn on something that is already on, would be not trying at all… seems one action less per trigger. Ill take them out, since your the experience here obviously, and see if I can spot a difference.

Again, yes it is! Though I am keen for nice looking, or even more importantly, easily checkable conditions, efficiency is of utmost importance. And again, if you say so, there’s no doubt in my mind I must change these template conditions into state conditions… And I will.

thank you!

1 Like

hmm:

      condition: template
      value_template: >
        {{states('sensor.saver_trash_tomorrow') != 'Geen'}}

we don’t have a state_not: do we? Now that would be a major PR…Since we can use that in several Lovelace cards, would you think it feasible to make it happen in the backend?

this

      condition: template
      value_template: >
        {{states('alarm_control_panel.ha_rpi4_alarm') in ['armed_away','armed_home']}}

could probably be written as 2 or conditions? would you still think that would be more efficient? If so, Id take it up…

Yes, that would probably be very simple to add, such as:

- condition: state
  entity_id: blah.blah
  state_not: abc

I couldn’t really say on the second question.

write it down and compare.
if it works and you like the way it looks then why not (but imho it’s more difficult to maintain if you need to change the entity_id or states being checked as they are in 2 different places)?
the question about efficiency is open and may change in the future so I wouldn’t be bothered :wink:

In is more efficient vs or. In relation to human time, it’s negligible. In regards to processing and memory, in out performs other methods in both memory consumption and time. If you made it a tuple, it would perform faster with the least memory consumed at a relatively fast speed:

      condition: template
      value_template: >
        {{ states('alarm_control_panel.ha_rpi4_alarm') in ('armed_away','armed_home') }}

tuples are denoted by ().

Using a list will be the fastest []. but it consumes a little more memory. about 50 bites 15 bites more.

isn’t memory released when the condition is checked?

In a perfect world yes but that’s not the case with automatic garbage collection.

I think (…) I am looking for speed, since most issues my setup seems to suffer from are timing issues, which are made visible by the Hue entities goin ‘unavailable’. My hope is to rule out as many timing problems as possible.

for the above:

condition: template
  value_template: >
    {{states('alarm_control_panel.ha_rpi4_alarm') in ['armed_away','armed_home']}}

could be written as:

condition:
  condition: or
  conditions:
    - condition: state
      entity_id: alarm_control_panel.ha_rpi4_alarm
      state: armed_away
    - condition: state
      entity_id: alarm_control_panel.ha_rpi4_alarm
      state: armed_home

for it to be faster? (fastest of the 3 …)?

that I cannot answer. I’d be willing to bet that the template is faster and less memory.

a well, ok, thanks, Ill leave t for now then, have just finished my above scanning exercise for the other state conditions… will first see if that made any difference :wink: