ipython: Global variables undefined in interactive use of embedded ipython shell

Original Launchpad bug 399627: https://bugs.launchpad.net/ipython/+bug/399627 Reported by: h-fangohr (Hans Fangohr).

The error can be reproduced as follows:

  1. Start Python, and start embedded ipython session. Following ipython’s manual, we do
fangohr@eta:~$ python
Python 2.4.3 (#1, Jun  8 2009, 14:09:06) 
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from IPython.Shell import IPShellEmbed
>>> ipshell=IPShellEmbed()
>>> ipshell()

Within the just started ipython session, global variables are sometimes not visible. Two examples are:

Example 1:

In [1]: a=1

In [2]: def f(x):
   ...:     return a*x
   ...: 

In [3]: f(2)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)

/home/fangohr/<ipython console> 

/home/fangohr/<ipython console> in f(x)

NameError: global name 'a' is not defined

Example 2:

In [4]: b=1

In [5]: (lambda :b)()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)

/home/fangohr/<ipython console> 

/home/fangohr/<ipython console> in <lambda>()

NameError: global name 'b' is not defined

There is no error if “b=1; (lambda :b)()” is put in a script, and this script is executed using ipython’s “run” command.

There is no error if “b=1; (lambda :b)()” is executed interactively after having started ipython.

The only way the error seems comes up is if an embedded IPython shell is started from a Python prompt AND the commands are executed interactively at the prompt.

I find the same error when trying ipython-0.9.1 (with python2.4).

The bug was reported by Olivier Klein to the nmag team (http://nmag.soton.ac.uk).

About this issue

  • Original URL
  • State: open
  • Created 14 years ago
  • Reactions: 6
  • Comments: 39 (17 by maintainers)

Commits related to this issue

Most upvoted comments

As noted at https://github.com/inducer/pudb/issues/103, a temporary workaround while using an embedded shell is: globals().update(locals()) (after defining the locally global variables, only).

I don’t understand, and it makes me angry.

Yup, I think it was fixed for Django 1.6. If you really can’t upgrade, you might want to apply the fix manually. It looks like this was it: https://github.com/django/django/commit/3570ff734e93f493e023b912c9a97101f605f7f5

AFAIK, my comments from a few years ago stand:

  1. I believe we are limited by the way Python itself works. Closures and dynamic evaluation don’t play well together, and IPython can’t fix it. People have found workarounds to move local variables to a global namespace, but those are hacks which can cause other problems, because they’re modifying the global namespace. I don’t plan on putting such workarounds into IPython; I’d rather leave an issue with something we’re not doing than introduce one by trying to be too clever.

  2. Many places where people thought they wanted embed(), they should actually use start_ipython() instead and avoid this kind of issue.

If I recall correctly, this was fixed for a little while, and seems to be reintroduced (reproduced using IPython 5.1.0 on macOS here: https://git.io/vPDrJ).

(edit: I may be mis-remembering the fix. It’s possible I just threw everything I needed into a startup file instead of using embed)