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.