title: How to access a variable defined in an outer function from inner function
body: <p>I have a dashboard where a dataframe is defined and displayed based upon the parameters chosen by the user. I would like to add a button that allows the user to download the dataframe, that it is previously defined, when it is clicked.
  The following is the function that I defined to define and to display the dataframe:</p>
  <pre><code>def filtra_dati(selezione, canale, metrica):
      output.clear_output()
          
      if canale == &quot;ALL&quot;:
          df = canali_weekly.loc[(slice(None), slice(selezione[0],selezione[1])), list(metrica)]  
      else:
          df = canali_weekly.loc[(canale, slice(selezione[0],selezione[1])), list(metrica)]
      
      with output:
          pd.set_option('display.max_columns', None)
          pd.set_option('display.max_rows', None)
          display(df)
  </code></pre>
  <p>I tried to nest a new function (<code>on_button_clicked()</code>) to add the download button:</p>
  <pre><code>def filtra_dati(selezione, canale, metrica):
      output.clear_output()
          
      if canale == &quot;ALL&quot;:
          df = canali_weekly.loc[(slice(None), slice(selezione[0],selezione[1])), list(metrica)]  
      else:
          df = canali_weekly.loc[(canale, slice(selezione[0],selezione[1])), list(metrica)]
      
      with output:
          pd.set_option('display.max_columns', None)
          pd.set_option('display.max_rows', None)
          display(df)
          
      def on_button_clicked(b):
          with output:
              print(&quot;Button clicked.&quot;)
              df.to_excel(&quot;~/Downloads/df.xlsx&quot;)
  </code></pre>
  <p>But it doesn't work and I get the error that the dataframe is not defined, which makes me think that I'am not able to access the variable defined above with this solution.</p>
  <pre><code>---------------------------------------------------------------------------
  NameError                                 Traceback (most recent call last)
  &lt;ipython-input-10-0246293b959d&gt; in on_button_clicked(b)
       42     with output:
       43         print(&quot;Button clicked.&quot;)
  ---&gt; 44         df.to_excel(&quot;~/Downloads/df.xlsx&quot;)
       45 
       46 
  
  NameError: name 'df' is not defined
  </code></pre>
  <p>I <a href="https://www.programiz.com/python-programming/closure#:%7E:text=A%20function%20defined%20inside%20another,in%20order%20to%20modify%20them." rel="nofollow noreferrer">read something</a> about nesting function but I'm not sure that is what I am looking for.</p>
  <p><strong>EDIT</strong>
  This is the full code:</p>
  <pre><code>kpi = [k for k in canali_weekly.columns]
  dropdown_canali = widgets.Dropdown(options = crea_opzioni_con_ALL(canali_weekly.index.get_level_values(level=0)), description='Canali:')
  select_metriche = widgets.SelectMultiple(options=kpi, value= kpi, rows=5, description='Metriche:')
  
  download_dataframe = widgets.Button(description='Scarica i dati', icon='check')
  
  def filtra_dati(selezione, canale, metrica):
      output.clear_output()
          
      if canale == &quot;ALL&quot;:
          df = canali_weekly.loc[(slice(None), slice(selezione[0],selezione[1])), list(metrica)]  
      else:
          df = canali_weekly.loc[(canale, slice(selezione[0],selezione[1])), list(metrica)]
      
      with output:
          pd.set_option('display.max_columns', None)
          pd.set_option('display.max_rows', None)
          display(df)
          
      def on_button_clicked(b):
          with output:
              print(&quot;Button clicked.&quot;)
              df.to_excel(&quot;~/Downloads/df.xlsx&quot;)
  
  
          
          
  def week_eventhandler(change):
      filtra_dati(change.new, dropdown_canali.value, select_metriche.value)       
  
  def canali_eventhandler(change):
      filtra_dati(intRange_week.value, change.new, select_metriche.value)     
      
  def metriche_eventhandler(change):
      filtra_dati(intRange_week.value, dropdown_canali.value, change.new) 
      
  intRange_week.observe(week_eventhandler, names='value')
  dropdown_canali.observe(canali_eventhandler, names='value')
  select_metriche.observe(metriche_eventhandler, names='value')
  
  download_dataframe.on_click(on_button_clicked)
  </code></pre>