Skip to content
This repository

IPython embed doesn't respect namespaces #954

Closed
certik opened this Issue October 30, 2011 · 5 comments

3 participants

Ondřej Čertík Min RK Thomas Kluyver
Ondřej Čertík

In Qsnake, where we embed IPython manually, the local namespace from Qsnake is exposed to IPython, which is a bug. Here is a simple script to reproduce the problem:


ondrej@eagle:~$ qsnake --shell
Type CTRL-D to exit the Qsnake shell.
Qsnake: ondrej@eagle:~$ python
Python 2.6.4 (r264:75706, May  7 2011, 22:48:31) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import IPython
>>> c = IPython.config.loader.Config()
>>> c.InteractiveShell.confirm_exit = False
>>> banner = "test"
>>> namespace = {}
>>> IPython.frontend.terminal.embed.InteractiveShellEmbed(config=c,
...             user_ns=namespace, banner1=banner).mainloop()
test
In [1]: c                                                                      
Out[1]: {'InteractiveShell': {'confirm_exit': False}}

In [2]: namespace                                                              
Out[2]: 
{'IPython': <module 'IPython' from '/home/ondrej/repos/qsnake/local/lib/python2.6/site-packages/IPython/__init__.pyc'>,
 'In': ['', u'c', u'namespace'],
 'Out': {1: {'InteractiveShell': {'confirm_exit': False}}},
 '_': {'InteractiveShell': {'confirm_exit': False}},
 '_1': {'InteractiveShell': {'confirm_exit': False}},
 '__': '',
 '___': '',
 '__builtin__': <module '__builtin__' (built-in)>,
 '__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__name__': '__main__',
 '__package__': None,
 '_dh': [u'/home/ondrej'],
 '_i': u'c',
 '_i1': u'c',
 '_i2': u'namespace',
 '_ih': ['', u'c', u'namespace'],
 '_ii': u'',
 '_iii': u'',
 '_oh': {1: {'InteractiveShell': {'confirm_exit': False}}},
 '_sh': <module 'IPython.core.shadowns' from '/home/ondrej/repos/qsnake/local/lib/python2.6/site-packages/IPython/core/shadowns.pyc'>,
 'banner': 'test',
 'c': {'InteractiveShell': {'confirm_exit': False}},
 'exit': <IPython.core.autocall.ExitAutocall at 0x28a7410>,
 'get_ipython': <bound method InteractiveShellEmbed.get_ipython of <IPython.frontend.terminal.embed.InteractiveShellEmbed object at 0x7f1517bce990>>,
 'help': Type help() for interactive help, or help(object) for help about object.,
 'namespace': {...},
 'quit': <IPython.core.autocall.ExitAutocall at 0x28a7410>}

In [3]: banner                                                                 
Out[3]: 'test'

As you can see, the c, banner and namespace variables are declared in Python above, but somehow they get propagated to IPython. What is worse, if you do:

In [4]: from sympy import var                                                  

In [5]: var("c")                                                               
Out[5]: c

In [6]: c                                                                      
Out[6]: {'InteractiveShell': {'confirm_exit': False}}

So the c variable can't be used in sympy (that's how I discovered this problem).

Min RK
Owner

I believe that the point of embed is to load IPython in the calling scope. If you want to clobber that behavior, you have to set the local_ns and global_ns arguments to shell.mainloop, which default to inspecting the calling frame:

>>> import IPython
>>> c = IPython.config.loader.Config()
>>> c.InteractiveShell.confirm_exit = False
>>> banner = "test"
>>> namespace = dict(a=5)
>>> shell = IPython.frontend.terminal.embed.InteractiveShellEmbed(config=c, user_ns=namespace, banner1=banner)
>>> shell.mainloop(local_ns=dict(b=10), global_ns=dict(d=32))
test
In [1]: a
Out[1]: 5

In [2]: b
Out[2]: 10

In [3]: c
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/Users/minrk/dev/ip/mine/<ipython-input-3-2cd6ee2c70b0> in <module>()
----> 1 c

NameError: name 'c' is not defined

In [4]: d
Out[4]: 32
Thomas Kluyver
Collaborator

N.B. global_ns might at some point turn into module (I've had a PR open for some time). You might want to look at instantiating TerminalInteractiveShell, rather than calling embed(). Have a look at the examples here.

Min RK
Owner

@takluyver - should this be closed as 'not an Issue', because embed seems to behave precisely as intended?

Ondřej Čertík

I have fixed this in the commit:

qsnake/qsnake@4daa75d

so I am closing this issue. Here is the line, that I use now:

IPython.frontend.terminal.embed.InteractiveShellEmbed(config=c,
        user_ns=namespace, banner1=banner).mainloop(local_ns={},
                global_ns={})

What is confusing to me is that there is user_ns and also local_ns (and global_ns). But I simply set local_ns and global_ns to an empty dictionary and use user_ns as the local namespace and things work as expected.

Thanks for the help!

Ondřej Čertík certik closed this November 14, 2011
Thomas Kluyver
Collaborator

There's probably an issue that it's a bit unclear. I'll try to get round to having a look at it in my usermod branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.