How to reload modules in django shell?

PythonDjangoIpython

Python Problem Overview


I am working with Django and use Django shell all the time. The annoying part is that while the Django server reloads on code changes, the shell does not, so every time I make a change to a method I am testing, I need to quit the shell and restart it, re-import all the modules I need, reinitialize all the variables I need etc. While iPython history saves a lot of typing on this, this is still a pain. Is there a way to make django shell auto-reload, the same way django development server does?

I know about reload(), but I import a lot of models and generally use from app.models import * syntax, so reload() is not much help.

Python Solutions


Solution 1 - Python

I'd suggest use IPython autoreload extension.

./manage.py shell

In [1]: %load_ext autoreload
In [2]: %autoreload 2

And from now all imported modules would be refreshed before evaluate.

In [3]: from x import print_something
In [4]: print_something()
Out[4]: 'Something'

 # Do changes in print_something method in x.py file.

In [5]: print_something()
Out[5]: 'Something else'

Works also if something was imported before %load_ext autoreload command.

./manage.py shell
In [1]: from x import print_something
In [2]: print_something()
Out[2]: 'Something'

 # Do changes in print_something method in x.py file.

In [3]: %load_ext autoreload
In [4]: %autoreload 2
In [5]: print_something()
Out[5]: 'Something else'

There is possible also prevent some imports from refreshing with %aimport command and 3 autoreload strategies:

> %autoreload > > - Reload all modules (except those excluded by %aimport) automatically > now. > > %autoreload 0 > > - Disable automatic reloading. > > %autoreload 1 > > - Reload all modules imported with %aimport every time before executing > the Python code typed. > > %autoreload 2 > > - Reload all modules (except those excluded by %aimport) every time > before executing the Python code typed. > > %aimport > > - List modules which are to be automatically imported or not to be > imported. > > %aimport foo > > - Import module ‘foo’ and mark it to be autoreloaded for %autoreload 1 > > %aimport -foo > > - Mark module ‘foo’ to not be autoreloaded.

This generally works good for my use, but there are some cavetas:

> - Replacing code objects does not always succeed: changing a @property in a class to an ordinary method or a method to a member variable can cause problems (but in old objects only). > - Functions that are removed (eg. via monkey-patching) from a module before it is reloaded are not upgraded. > - C extension modules cannot be reloaded, and so cannot be autoreloaded.

Solution 2 - Python

My solution to it is I write the code and save to a file and then use:

> python manage.py shell < test.py

So I can make the change, save and run that command again till I fix whatever I'm trying to fix.

Solution 3 - Python

I recommend using the django-extensions project like stated above by dongweiming. But instead of just 'shell_plus' management command, use:

manage.py shell_plus --notebook

This will open a IPython notebook on your web browser. Write your code there in a cell, your imports etc. and run it.

When you change your modules, just click the notebook menu item 'Kernel->Restart'

There you go, your code is now using your modified modules.

Solution 4 - Python

look at the manage.py shell_plus command provided by the django-extensions project. It will load all your model files on shell startup. and autoreload your any modify but do not need exit, you can direct call there

Solution 5 - Python

It seems that the general consensus on this topic, is that python reload() sucks and there is no good way to do this.

Solution 6 - Python

Use shell_plus with an ipython config. This will enable autoreload before shell_plus automatically imports anything.

pip install django-extensions
pip install ipython
ipython profile create

Edit your ipython profile ( ~/.ipython/profile_default/ipython_config.py):

c.InteractiveShellApp.exec_lines = ['%autoreload 2']
c.InteractiveShellApp.extensions = ['autoreload']

Open a shell - note that you do not need to include --ipython:

python manage.py shell_plus

Now anything defined in SHELL_PLUS_PRE_IMPORTS or SHELL_PLUS_POST_IMPORTS (docs) will autoreload!

Note that if your shell is at a debugger (ex pdb.set_trace()) when you save a file it can interfere with the reload.

Solution 7 - Python

My solution for this inconvenient follows. I am using IPython.

$ ./manage.py shell
> import myapp.models as mdls   # 'mdls' or whatever you want, but short...
> mdls.SomeModel.objects.get(pk=100)
> # At this point save some changes in the model
> reload(mdls)
> mdls.SomeModel.objects.get(pk=100)

For Python 3.x, 'reload' must be imported using:

from importlib import reload

Hope it helps. Of course it is for debug purposes.

Cheers.

Solution 8 - Python

Reload() doesn't work in Django shell without some tricks. You can check this thread na and my answer specifically:

https://stackoverflow.com/questions/890924/how-do-you-reload-a-django-model-module-using-the-interactive-interpreter-via-ma/3466579#3466579

Solution 9 - Python

Using a combination of 2 answers for this I came up with a simple one line approach.

You can run the django shell with -c which will run the commands you pass however it quits immediately after the code is run.

The trick is to setup what you need, run code.interact(local=locals()) and then re-start the shell from within the code you pass. Like this:

python manage.py shell -c 'import uuid;test="mytestvar";import code;code.interact(local=locals())'

For me I just wanted the rich library's inspect method. Only a few lines:

python manage.py shell -c 'import code;from rich import pretty;pretty.install();from rich import inspect;code.interact(local=locals())'

Finally the cherry on top is an alias

alias djshell='python manage.py shell -c "import code;from rich import pretty;pretty.install();from rich import inspect;code.interact(local=locals())"'

Now if I startup my shell and say, want to inspect the form class I get this beautiful output: enter image description here

Solution 10 - Python

Instead of running commands from the Django shell, you can set up a management command like so and rerun that each time.

Solution 11 - Python

Not exactly what you want, but I now tend to build myself management commands for testing and fiddling with things.

In the command you can set up a bunch of locals the way you want and afterwards drop into an interactive shell.

import code

class Command(BaseCommand):
  def handle(self, *args, **kwargs):
     foo = 'bar'
     code.interact(local=locals())

No reload, but an easy and less annoying way to interactively test django functionality.

Solution 12 - Python

import test  // test only has x defined
test.x       // prints 3, now add y = 4 in test.py
test.y       // error, test does not have attribute y

solution Use reload from importlib as follows

from importlib import reload
import test // test only has x defined
test.x // prints 3, now add y = 4 in test.py
test.y // error
reload(test)
test.y // prints 4

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMad WombatView Question on Stackoverflow
Solution 1 - PythonPaweł BB DrozdView Answer on Stackoverflow
Solution 2 - PythonErikView Answer on Stackoverflow
Solution 3 - PythonmpafView Answer on Stackoverflow
Solution 4 - PythondongweimingView Answer on Stackoverflow
Solution 5 - PythonMad WombatView Answer on Stackoverflow
Solution 6 - PythonandorovView Answer on Stackoverflow
Solution 7 - PythonRoqueView Answer on Stackoverflow
Solution 8 - PythonTomasz ZielińskiView Answer on Stackoverflow
Solution 9 - PythonJohn JView Answer on Stackoverflow
Solution 10 - PythonlittlegreenView Answer on Stackoverflow
Solution 11 - PythontoabiView Answer on Stackoverflow
Solution 12 - PythonAkshay Vijay JainView Answer on Stackoverflow