Strange behaviour Django shell and iPython

224 views Asked by At

I was doing some stuff in the Django console and I realized that the global variables are not recognized inside the lambda expression, for example if you execute the following code inside a python or even inside an iPython console it works perfectly:

a = 10
foo = lambda x: x + a
foo(10) # returns 20

But if you execute it inside the Django shell with iPython it doesn't work:

In [8]: foo = lambda x: x + a

In [9]: a = 10

In [10]: foo(10)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 foo(10)

/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <lambda>(x)
----> 1 foo = lambda x: x + a

NameError: global name 'a' is not defined

The iPython version 0.13.2

Thank you in advance!

EDIT

Event if I assign a before the lambda funciton the problem stills:

In [1]: a = 10

In [2]: foo = lambda x: x + a                                                                                                                                                                                                                  

In [3]: foo(10)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 foo(10)

/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <lambda>(x)
----> 1 foo = lambda x: x + a

NameError: global name 'a' is not defined

In [4]: 
───────────
1

There are 1 answers

0
Nitzle On BEST ANSWER

You might be experiencing the bug others have encountered here:

https://github.com/ipython/ipython/issues/62#issuecomment-3854940

As explained in the thread a little further down, prior to version 1.6, django was starting the ipython shell using the IPython.embed() function, which was forcing ipython to start with separate local and global namespaces.

The django team fixed this issue in 1.6 in this commit: https://github.com/django/django/commit/3570ff734e93f493e023b912c9a97101f605f7f5

Here is a backport fix for older versions of Django (1.4.14 in this case): https://github.com/theatlantic/django/commit/9dfe12c40af23956dc12e3427e3e7e63ebc360c9

You can reproduce this issue if you manually call IPython.embed() inside of another function (creating a closure), even if you use a regular python/ipython shell. Tested with ipython 3.1.0:

>>> from IPython import embed
>>> def test():
...     embed()
... 
>>> test()
Python 2.7.9 (default, Feb 10 2015, 03:28:08) 
Type "copyright", "credits" or "license" for more information.

IPython 3.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: a = 10

In [2]: foo = lambda x: x+a

In [3]: foo(10)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-08cbc4a9df91> in <module>()
----> 1 foo(10)

<ipython-input-2-3ecd5afea150> in <lambda>(x)
----> 1 foo = lambda x: x+a

NameError: global name 'a' is not defined