Can I use IPython embed() to change the state of a function?

Viewed 157

Is it possible to embed an IPython session inside a function such that it makes changes to the code as if it were in global namespace? If not, why? And are there alternatives?

From the entry on the IPython wiki regarding embedding an IPython session from the inside of a Python script:

It’s important to note that the code run in the embedded IPython shell will not change the state of your code and variables, unless the shell is contained within the global namespace.

A small example of this behavior is changing a variable from an IPython session, which is inside the Python REPL:

>>> from IPython import embed
>>> a = 12
>>> embed()

In [1]: a = 13

In [2]: exit()

>>> a
13

However when embedding inside a function:

>>> from IPython import embed
>>> def f():
...     x = 2
...     embed()
...     print(x)
... 
>>> f()

In [1]: x = 3

In [2]:                                                                  

2

Although I don't understand why it must be so (design choice? technical problems?) I would like to change my code with IPython outside the global namespace, i.e. a function, which should be allowed behavior, considering that most well structured programs will leave as little as possible to the global namespace (in my case I'm trying to change my main() function).

1 Answers

Please don't do this! This is just a PoC of how to hack around this design feature.

You are likely not going to find a solution that doesn't involve something similar. But I'll just leave this here so you can see how ugly a potential workaround could be.

from IPython import embed

def main():
  global g
  g = 40
  embed()
  print (g)

main()

Now inside the IPython repl, we do:

Python 3.9.2 (default, Feb 27 2021, 00:33:24)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.19.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: g += 2

In [2]: globals().update(dict(g=g))

In [3]:

The output:

42

Not only is it hacky, but it also touches the global namespace which according to you, is not desirable.

Related