1

Is it possible to get+set a higher context/scope's variables by passing the context itself?

I'd like to:

# main_jupyter.ipynb

from my_module import MyModule # class

var_to_access = 'foo'

my_module.set_var_to_bar(ipynb_context)
# my_module.py

class MyModule(object):
  def set_var_to_bar(self, ipynb_context):
    ipynb_context.eval('var_to_access')
    ipynb_context.eval('var_to_access = "bar"')

Sometime later in the notebook, I'd like to get bar out of var_to_access.

Specifically, I'm attempting to build a library for our data team that works within the context of papermill. Papermill passes in parameters via a tagged cell. The parameter cell will override local vars with whatever is passed in during the pm.execute_notebook

I'd like that specially tagged cell to be able to run anywhere so I don't have to worry about if the data time forgets and puts the tagged cell someplace random.

The goal being I can check if a variable has been defined (by parameters) and set it myself in the library/module if it's missing.

nitsujri
  • 1,448
  • 2
  • 16
  • 29

1 Answers1

0

I learned there are two ways. Sticking with the example above:

First way

This first way is much more robust. You always have the right context. The difficulty is there's no way to abstract away getting to self.

# main_jupyter.ipynb
import sys
from my_module import MyModule # class

var_to_access = 'foo'

curr_name = globals()['__name__']
self = sys.modules[curr_name]

my_module.set_var_to_bar(self)

Second way

This second way is inside MyModule and we reach into the stacktrace and grab the 'most recent' module. It assumes this is what called your function. Way more brittle, but in my specific use it's perfect. Less code for the data-team to mess-with/worry-about when accessing external resources.

class MyModule(object):
  def set_var_to_bar(self):
    mod = inspect.getmodule(inspect.stack()[1][0])

    exec('mod.var_to_access = "bar"')
nitsujri
  • 1,448
  • 2
  • 16
  • 29