PyScript version 1.0.0 Released!

PyScript 1.0.0 has been released!

If you’re not already using PyScript, written by @craigb, you’re in for a treat. If you are, skip down a bit to see some highlights of the new features in this release.

What is PyScript?

PyScript is an alternative implementation for Home Assistant Automations. Similar in functionality to Node-RED’s Home Assistant integration or AppDaemon, it allows you to write Home Assistant Automations in what will be, for some, a much simpler syntax.

As an example, in Home Assistant, you might want to turn on a light for 5 minutes anytime a motion detector senses motion and it’s dark outside. That automation might look like this:

- alias: porch lights on
  trigger:
    - platform: template
      value_template: >-
        {{
            is_state('binary_sensor.motion', 'on')
            and is_state('binary_sensor.dark', 'on')
        }}
  action:
    service: light.turn_on
    data:
      entity_id: light.porch
      brightness: 255
      color_temp: 300

- alias: porch lights off
  trigger:
    - platform: state
      entity_id: binary_sensor.motion
      to: "off"
      for: 300
  action:
    - service: light.turn_off
      data:
        entity_id: light.porch

In PyScript, that automation might look like this:

@state_trigger('binary_sensor.motion == "on" and binary_sensor.dark == "off"')
def porch_lights_on():
  light.porch.turn_on(brightness=255, color_temp=300)

@state_trigger('binary_sensor.motion == "off"', state_hold=300)
def porch_lights_off():
  light.porch.turn_off()

PyScript offers many more features all designed to keep automations easy to read, even when the actions they perform are complex. If you’ve ever written a Home Assistant Automation with the choose action in it, you’ll likely really appreciate the simpler form for this kind of logic in PyScript.

PyScript lets you use Python, instead of YAML, to write your automations. And with this comes nearly all of the Python language features. Python is incredibly simple to write – certainly not any more difficult than Home Assistant Automation YAML – and is designed to express logic like this.


New Features in 1.0.0

In this release there are a couple of very notable features.

Short Form Service Calls

Before this release, turning on a light looked like this:

light.turn_on(entity_id='light.porch')

Now, while that syntax still works, you can instead do this:

light.porch.turn_on()

Any service call that requires an entity_id can be shortened in this way. While, in a single line like this, it make not look like much, it does a lot to improve the readability of your automation, and it requires fewer keystrokes.

State Persistence

There are times when an automation works best if we can store some piece of data and retrieve it later and we want that information to be maintained even if we need to restart Home Assistant.

Perhaps, for some reason, you need to keep track of how many times a switch has turned on. In Home Assistant automations, you’d likely use a counter helper, or maybe an input_number.

First, you have to create that helper. Once created, you might write an automation like this:

- alias: count my thing
  trigger:
    - platform: state
      entity_id: switch.my_thing
      to: "on"
  action:
    - service: counter.increment
      data:
        entity_id: counter.my_thing

In PyScript, you don’t need the helper at all. Instead that automation might look like this:

state.persist('pyscript.switch_counter', default_value="0")

@state_trigger('switch.my_thing == "on"')
def count_my_thing():
  pyscript.switch_counter = int(pyscript.switch_counter) + 1

The state.persist call lets PyScript know that you want this state to be persisted. After that, you can just update it like any other variable. If you don’t need the data restored after a Home Assistant restart, you can leave the state.persist call out entirely and the rest will still work as you’d expect.

Working with Attributes

A lot of times, in Home Assistant Automations the solution to working with an attribute is to write a Template Sensor to expose that attribute in its own entity_id and then write your Automation against this new entity_id. With PyScript, that is, of course, still an option. But, in this release, all @state_triggers and task.wait_until() calls can use attributes directly.

Perhaps you want to get a notification if your thermostat is set higher than 80 degrees:

@state_trigger('climate.thermostat.temperature > 80')
def send_thermostat_notification():
  notify.me(
      message=f"The Thermostat is now set to {climate.thermostat.temperature}, which is above 80"
  )

Using task.wait_until() you can also get a notification when the thermostat setpoint is restored to a more reasonable setting:

@state_trigger('climate.thermostat.temperature > 80')
def send_thermostat_notification():
  task.unique('thermostat_notification')
  notify.me(
      message=f"The Thermostat is now set to {climate.thermostat.temperature}, which is above 80"
  )
  task.wait_until(state_trigger="climate.thermostat.temperature <= 80")
  notify.me(
      message=f"The Thermostat is now set below 80 degrees"
  )

state_hold on @state_trigger

The state_hold kwarg on a @state_trigger works similar to the for: option in a Home Assistant Automation Trigger. Before this feature, you had to jump through a few extra hoops with task.unique() and task.sleep() in order to wait for an entity to be in a certain state for a certain amount of time. But that’s no longer the case.

Logbook logging

When Home Assistant Automations fire, if you use the Logbook, you can consult it to see which automation turned on what. This helps answer the question “Why is this light on?” when Automations don’t work exactly like we thought they would.

With this release, you’ll see PyScript automations appearing in the logbook too, giving you a record of which PyScript turned on which light and when.

VSCode Jupyter Kernel

PyScript has an optional Jupyter Notebook kernel you can use. This provides entity_id completion and also allows you to test automations without having to reload PyScript after every change. Once you have it working the way you want, you copy and paste the code into the PyScript directory and you’re done.

In this release, PyScript’s Jupyter Kernel works with VSCode’s Jupyter Notebook implementation. This means if you’re using VSCode to edit your Automations and PyScript files, you don’t have to leave that environment to test out some new code using Jupyter Notebook.

Much More

I’ve only highlighted a few of the new features available.

Check out the full release notes to get the details on all the changes in this release.

Share!

Share in the comments one of your PyScript automations to help others get a feel for just how easy automations can be with PyScript.

7 Likes

Wish I could upvote this more than once! The enhancements and improvements are fantastic. Thank you to all who have contributed to PyScript’s rapid evolution.

In my opinion, PyScript has quickly grown to be far more capable than the existing python_script integration (and easier to use) that it merits superseding it as Home Assistant’s officially supported “python script” integration.

FWIW, I really like the new compact syntax:

  light.porch.turn_on(brightness=255, color_temp=300)
1 Like

I agree. I never got much mileage out of python_script. Even when dodging around the more complicated syntax, I still had to have an “automation” to get anywhere with it since they can only be used as services.

The syntax in pyscript is MUCH nicer. And, they can be triggered without also needing a Home Assistant automation, so that works out really well.

1 Like

Is there much (any) overhead compared to the core automation method?

I know very little about python but the examples you have shown are very tempting.

I can’t imagine there is much. When it all boils down, regular native Home Assistant Automations are implemented in much the same way using the same state and event API. There may be some preferential treatment to run native Automations First (I don’t know, I haven’t dug through all that code), but otherwise, you should be unable to tell in operation if it was pyscript or native.

The other alternative automation platforms mentioned (Node-RED and AppDaemon) use the websocket API. Even then, they are plenty fast for most use cases. But PyScript should be even faster than those since there’s no websocket to deal with and the API it uses is the same one used by Native Automations.

3 Likes

Hi
I just tried iPyScript( installed it through HACS) on HomeAssistant 0.118.0).
Installation runs smoothly and I’ve added a custom py script to the config folder.
But after multiple restarts the pyscript service is not showing up in the services tab.
I can not find any issues in the logs.
In addition my custom py script ( pyscript.myscript_ ) does not show up.

Any idea what could fix this ?

Thanks

You need to either add the integration via the Integrations UI or include “pyscript:” in your configuration.yaml.

I’ve found categories like python_script, appdaemon, … but NO PYSCRIPT.
Wouldn’t it be nice to have a separate category for PYSCRIPT? with subcategories?
I like pyscript very much. There’s the separate https://hacs-pyscript.readthedocs.io/en/latest/index.html
but, no community around it. The pyscript code is here and there on this site. Not easy to find. (at least, not for me)
A place, dedicated to pyscript users, would be so nice.
and… I hope one day, pyscript can be added to Core. It’s too important in my view.

I agree, pyscript should be a category in these forums. I’ve contacted a maintainer about adding it, but it hasn’t happened yet.

Github offers a discussions feature. Perhaps that could be turned on? @craigb

I just reached out to an admin for the community forums to request a subcategory for pyscript. Let’s see if that succeeds.

Otherwise I’ll look at the GitHub alternative.

thanks! Looking forward to it :slight_smile: