how to reload a Class in python shell?
Question:
If I import a module defining a class of the same name belonging to a package, it is imported as a Class, not a Module because of the __init__.py of the parent package. See different import results at different directories for details. In Python shell or ipython shell, if I do
from MyPak import MyMod
MyModule is always imported as Class thus I can not reload it (reload() works only for modules). Run
from MyPak import MyMod
again does not seem to update the Class definition. Could anyone suggest a way to update the class in python shell?
ps. without restarting the python interpreter.
pps. Just in case you have the code in hand and want to test it: I am actually talking about BioPython, and I am working on Bio.PDB.PDBParser. I have an ipython shell (v0.10) and edit PDBParser.py. Just got no way to reload it in ipython.
so here is what I did:
# start ipython v0.10
import Bio
from Bio.PDB import PDBParser
p = PDBParser()
s = p.get_structure()
# then I make changes,e.g. simply print some text, in PDBParser.py
del Bio
del PDBParser
del s
import Bio # or reload(Bio) without deleting all the objects
from Bio.PDB import PDBParser
p = PDBParser()
s = p.get_structure() # expected output after change not seen :(
I could not see the printed text. The changes were not applied somehow.
Answers:
On Python 3 only, import the reload
function:
>>> from importlib import reload
On both Python 2.x, and 3.x, you can then simply call reload
on the module:
>>> import MyPak
>>> reload(MyPak)
>>> from MyPak import MyMod
However, instances of the old class will not be updated (there’s simply no code that describes the update mechanism).
I finally found the answer:
import MyPak
from MyPak import MyMod
after editing MyPak/MyMod.py
file, to reload the class MyMod
in the file MyMod.py
, one needs to
import sys
del sys.modules['MyPak.MyMod']
reload(MyPak)
from MyPak import MyMod
Caveats:
-
Executing del MyPak
or del MyMod
or del MyPak.MyMod
does not solve the problem since it simply removes the name binding. Python only searches sys.modules
to see whether the modules had already been imported. Check out the discussion in the post module name in sys.modules and globals().
-
When reloading MyPak, python tries to execute the line from MyMod import MyMod
in MyPak/__init__.py
. However, it finds MyPak.MyMod
in sys.modules
, thus it will NOT
reload MyMod
although MyPak/MyMod.py
has been updated. And you will find that no new MyPak/MyMod.pyc
is generated.
You can use a magic function:
%load_ext autoreload
%autoreload 2
from MyPak import MyMod
It also works for function imports:
%load_ext autoreload
%autoreload 2
from anypythonfile import my_function
This magic function works in Python 2.x (I’ve tested on 2.7+) and Python 3.x (I’ve tested on 3.7).
I have one myfile.py file which contains one class MyClass
To import just do:
from myfile import MyClass
mc = MyClass()
To reload:
import sys
del sys.modules['myfile']
from myfile import MyClass
modifiedmc = MyClass()
This is very useful while building modules.
one can put these inside a function and just call the function
def myreload():
import sys
del sys.modules['myfile']
from myfile import MyClass
modifiedmc = MyClass()
global mc
mc = modifiedmc
It works for me using python 3.5.2:
import importlib
importlib.reload(class)
from class import module
There are thee ways to solve this:
1. Use import MyPak.MyMod
instead of from MyPak import MyMod
Then you can write:
from importlib import reload # If on Python 3
import MyPak.MyMod
reload(MyPak.MyMod)
and it works.
2. Use IPython.lib.deepreload
from MyPak import MyMod
from IPython.lib.deepreload import reload
reload(MyPak) # This should also reload all submodules
3. Use autoreload magic
%load_ext autoreload
%autoreload 2
import MyPak.MyMod # All changes to MyPak.MyMod will be loaded automatically
Here is shortest answer if you use Jupyter Notebook. You need change cell with
from your_function_name import YourClassName
to
from importlib import reload
import YourClassName
reload(YourClassName)
from YourClassName import your_function_name
If I import a module defining a class of the same name belonging to a package, it is imported as a Class, not a Module because of the __init__.py of the parent package. See different import results at different directories for details. In Python shell or ipython shell, if I do
from MyPak import MyMod
MyModule is always imported as Class thus I can not reload it (reload() works only for modules). Run
from MyPak import MyMod
again does not seem to update the Class definition. Could anyone suggest a way to update the class in python shell?
ps. without restarting the python interpreter.
pps. Just in case you have the code in hand and want to test it: I am actually talking about BioPython, and I am working on Bio.PDB.PDBParser. I have an ipython shell (v0.10) and edit PDBParser.py. Just got no way to reload it in ipython.
so here is what I did:
# start ipython v0.10
import Bio
from Bio.PDB import PDBParser
p = PDBParser()
s = p.get_structure()
# then I make changes,e.g. simply print some text, in PDBParser.py
del Bio
del PDBParser
del s
import Bio # or reload(Bio) without deleting all the objects
from Bio.PDB import PDBParser
p = PDBParser()
s = p.get_structure() # expected output after change not seen :(
I could not see the printed text. The changes were not applied somehow.
On Python 3 only, import the reload
function:
>>> from importlib import reload
On both Python 2.x, and 3.x, you can then simply call reload
on the module:
>>> import MyPak
>>> reload(MyPak)
>>> from MyPak import MyMod
However, instances of the old class will not be updated (there’s simply no code that describes the update mechanism).
I finally found the answer:
import MyPak
from MyPak import MyMod
after editing MyPak/MyMod.py
file, to reload the class MyMod
in the file MyMod.py
, one needs to
import sys
del sys.modules['MyPak.MyMod']
reload(MyPak)
from MyPak import MyMod
Caveats:
-
Executing
del MyPak
ordel MyMod
ordel MyPak.MyMod
does not solve the problem since it simply removes the name binding. Python only searchessys.modules
to see whether the modules had already been imported. Check out the discussion in the post module name in sys.modules and globals(). -
When reloading MyPak, python tries to execute the line
from MyMod import MyMod
inMyPak/__init__.py
. However, it findsMyPak.MyMod
insys.modules
, thus it will NOT
reloadMyMod
althoughMyPak/MyMod.py
has been updated. And you will find that no newMyPak/MyMod.pyc
is generated.
You can use a magic function:
%load_ext autoreload
%autoreload 2
from MyPak import MyMod
It also works for function imports:
%load_ext autoreload
%autoreload 2
from anypythonfile import my_function
This magic function works in Python 2.x (I’ve tested on 2.7+) and Python 3.x (I’ve tested on 3.7).
I have one myfile.py file which contains one class MyClass
To import just do:
from myfile import MyClass
mc = MyClass()
To reload:
import sys
del sys.modules['myfile']
from myfile import MyClass
modifiedmc = MyClass()
This is very useful while building modules.
one can put these inside a function and just call the function
def myreload():
import sys
del sys.modules['myfile']
from myfile import MyClass
modifiedmc = MyClass()
global mc
mc = modifiedmc
It works for me using python 3.5.2:
import importlib
importlib.reload(class)
from class import module
There are thee ways to solve this:
1. Use import MyPak.MyMod
instead of from MyPak import MyMod
Then you can write:
from importlib import reload # If on Python 3
import MyPak.MyMod
reload(MyPak.MyMod)
and it works.
2. Use IPython.lib.deepreload
from MyPak import MyMod
from IPython.lib.deepreload import reload
reload(MyPak) # This should also reload all submodules
3. Use autoreload magic
%load_ext autoreload
%autoreload 2
import MyPak.MyMod # All changes to MyPak.MyMod will be loaded automatically
Here is shortest answer if you use Jupyter Notebook. You need change cell with
from your_function_name import YourClassName
to
from importlib import reload
import YourClassName
reload(YourClassName)
from YourClassName import your_function_name