Hello @SRJDB ,
What youโre running into isnโt your Python variable misbehavingโitโs the widget hanging onto its own internal state. A Databricks widget will happily keep whatever value you gave it, per user and per notebook, until you explicitly clear or overwrite it. So when you do selection = '' in Python, that doesnโt touch the widgetโs bound value returned by dbutils.widgets.get(). To make things more fun, widgets also have a long-standing quirk where state doesnโt always clear after a Run All, which explains why the panel and the printed value sometimes disagree.
Letโs dig into why this happens.
-
dbutils.widgets.get() always returns the widgetโs stored value, not whatever Python variable you decide should be โthe truth.โ
-
Multiselect widgets send back a comma-delimited string. If nothing is selected it should be emptyโunless the widget resurrects a previous state or you recreate it with a baked-in default.
-
And that default matters. With defaultValue=widget_values[0], youโve guaranteed that every redefinition forces a selection. Thereโs no way to end up blank unless you explicitly allow one.
-
Bonus: after a Run All, widgets sometimes refuse to clear state, even if you remove/reset them in code. Running the cells individually usually sidesteps that. If you ever need fully consistent state behavior, ipywidgets are the more predictable path.
Now here are the patterns that actually work.
Option 1: Remove and recreate the widget before reading it.
And yesโremoval must happen in a different cell.
# Cell 1: Reset widget
try:
dbutils.widgets.remove("My widget")
except Exception:
pass
# Cell 2: Recreate and read
widget_values = spark.sql("""
SELECT my_column
FROM my_table
GROUP BY my_column
ORDER BY my_column
""").collect()
widget_values = [r[0] for r in widget_values]
choices = [""] + widget_values # Explicit blank
dbutils.widgets.multiselect("My widget", "", choices)
raw = dbutils.widgets.get("My widget")
selection_list = [s for s in raw.split(",") if s.strip()]
selection = "" if not selection_list else ",".join(selection_list)
Option 2: Add a labeled sentinel (โโ) and filter it out cleanly.
choices = ["<none>"] + widget_values
dbutils.widgets.multiselect("My widget", "<none>", choices)
raw = dbutils.widgets.get("My widget")
selection_list = [s for s in raw.split(",") if s and s != "<none>"]
selection = "" if not selection_list else ",".join(selection_list)
Option 3: Stop resetting the default to the first value.
This line guarantees a selection every time:
dbutils.widgets.multiselect("My widget", widget_values[0], widget_values)
If your goal is โblank unless chosen,โ this works against you.
A few extra notes:
-
If Run All bites you, run the reset/create cells manually or move to ipywidgets where state behaves like you expect.
-
Widgets speak strings only; multiselects always require you to parse the comma-delimited output.
-
Notebook jobs ignore whateverโs in the UIโthey start with defaults unless you pass overrides.
Hope this helps, Louis.