Django shell (IPython) gives NameError on dict comprehensions #2532

Closed
dhruvbaldawa opened this Issue Oct 30, 2012 · 11 comments

5 participants

@dhruvbaldawa
>>> from django.contrib.auth.models import User
>>> names = ['carl', 'jim', 'jack', 'john', 'mark']
# Now using some dict comprehension
>>> u = {name: User.objects.get(username=name) for name in names}
NameError: global name 'User' is not defined

However, the same works on default python shell
http://stackoverflow.com/questions/13135145/django-problems-when-using-dict-comprehensions-nameerror-global-name-user-is

@Carreau
IPython member

Hi,

I think this might be a mistake in django :
$ ipython

In [1]: names = ['carl', 'jim', 'jack', 'john', 'mark']

In [2]: n=1

In [3]: {name:n for name in names}
Out[3]: {'carl': 1, 'jack': 1, 'jim': 1, 'john': 1, 'mark': 1}

$django-admin.py startproject mysite
cd mysite
$ python manage.py shell

In [1]: names = ['carl', 'jim', 'jack', 'john', 'mark']

In [2]: n=1

In [3]: {name:n for name in names}
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django-1.4.2-py2.7.egg/django/core/management/commands/shell.pyc in <module>()
----> 1 {name:n for name in names}

/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Django-1.4.2-py2.7.egg/django/core/management/commands/shell.pyc in <dictcomp>((name,))
----> 1 {name:n for name in names}

NameError: global name 'n' is not defined

But my knowledge of django is ~ 0

@dhruvbaldawa

@Carreau you use python manage.py shell to access Django models/methods/modules. Also, Django returns the corresponding instances, and not the id.

This is not a problem with Django, because the same syntax works in default python shell, you can try that using python manage.py shell --plain

I understand the point you are making here, and I am not saying that django is perfect. But, we could investigate a little into this.

@Carreau
IPython member

I think this might be a mistake in django :

This is not a problem with Django, because the same syntax works in default python shell

Sorry, I was meaning the way django is launching IPython, I have no idea how manage.py does effectively decide to launch an IPython instance.

@dhruvbaldawa

I have IPython v0.13.
To me its just like getting and loading all the models, and then call self.run_shell() from line 64, and it calls ipython() from line 45. And, embed() provides the IPython shell. Any other thing, you can notice here ?

@Carreau
IPython member

Seem to be what was discussed in #62.

@takluyver
IPython member

Hi, yes, we've come across this problem before - the trouble is that Django uses embed(), which is intended for something slightly different. I've been meaning to properly define what API Django (and other applications) should use, but I haven't got round to it yet.

@minrk
IPython member

This bug has been fixed in django (by me). Closing here.

@minrk minrk closed this Jan 20, 2013
@johnpneumann

This does not appear to be fixed and looks like the same issue as in #62

In [1]: from datetime import datetime

In [2]: def test():
   ...:     print datetime.now()
   ...:

In [3]: test()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/Users/jneumann/svn/trunk/web/python/python-environments/pffenv/lib/python2.7/site-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 test()

/Users/jneumann/svn/trunk/web/python/python-environments/pffenv/lib/python2.7/site-packages/django/core/management/commands/shell.pyc in test()
      1 def test():
----> 2     print datetime.now()
      3

NameError: global name 'datetime' is not defined

In [4]: names = ['carl', 'jim', 'jack', 'john', 'mark']

In [5]: n=1

In [6]: {name:n for name in names}
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/Users/jneumann/svn/trunk/web/python/python-environments/pffenv/lib/python2.7/site-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 {name:n for name in names}

/Users/jneumann/svn/trunk/web/python/python-environments/pffenv/lib/python2.7/site-packages/django/core/management/commands/shell.pyc in <dictcomp>((name,))
----> 1 {name:n for name in names}

NameError: global name 'n' is not defined

Tested this in Django 1.5 and 1.5.1

@minrk
IPython member

I believe the fix is in django 1.6, not 1.5. Fixed versions of django don't use embedded IPython at all (it never should have), which is the relevant fix.

@johnpneumann

Got it. Thanks for the information. Well the easiest way to get around this issue is to just grab the following lines (from here https://github.com/django/django/blob/master/django/core/management/commands/shell.py) and replace the current implementation in your pyenv with this:

    def ipython(self):
        try:
            from IPython.frontend.terminal.ipapp import TerminalIPythonApp
            app = TerminalIPythonApp.instance()
            app.initialize(argv=[])
            app.start()
        except ImportError:
            # IPython < 0.11
            # Explicitly pass an empty list as arguments, because otherwise
            # IPython would use sys.argv from this script.
            try:
                from IPython.Shell import IPShell
                shell = IPShell(argv=[])
                shell.mainloop()
            except ImportError:
                # IPython not found at all, raise ImportError
                raise

Which would be located in the same location. Seemed to be a backwards compatible 1.5 change from what I've tested thus far. Thanks for the help @minrk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment