I am prototyping stuff in an IPython notebook that is loading Python2 code from modules on my computer. I activated reloading magic commands to make it easier to go back-and-forth between my text editor and the notebook when I make a code change and re-run a cell to see its affect:
%reload_ext autoreload
%autoreload 2
I am working in Python 2.7.10 because I working with some legacy code that doesn't compile for 3. Part of my work is extending some classes in this legacy code and overloading some of their methods. But, I also need to call some of the original base methods to do important work. For example:
class LegacyBase:
def important_method(self):
#old stuff i'll need
class NewClass(LegacyBase):
#overload base method
def important_method(self):
#do some new stuff
while 1:
#call old method to do stuff
super(NewClass, self).important_method() #use old Python2 super calls :(
#some break conditions
When I call important_method()
with some NewClass
instance the first time in my notebook (meaning, after a kernel reset) it runs fine. The loop is such that the super
call is happening more than once! No errors
But, if I go and modify some code to my new method in my text editor and go back to the IPython cell and call it again I get the following error at the line in my overloaded important_method()
where the super
call is made.
TypeError: super(type, obj): obj must be an instance or subtype of type
Note: I tried just naming my new method a different name because I thought it was something to do with the overloading method calling itself again but that didn't help. Also, I want them to be the same name because this is an API method and I want users of the legacy code to be able to call the same methods they know from before.
Any idea how to use reloading in IPython notebooks with these Python2 super
calls?
Thanks!
Your existing instances are still pointing to the old class from before the reload.
You need to either re-create the instances, or update their __class__
attribute:
instance_of_newclass.__class__ = NewClass
I use a module reload_test.py
modeled after your example:
class LegacyBase:
def important_method(self):
print 'doing'
class NewClass(LegacyBase):
def important_method(self):
for x in range(3):
super(NewClass, self).important_method()
In my IPython Notebook:
In [1]: %reload_ext autoreload
%autoreload 2
In [2]: import reload_test
In [3]: nc = reload_test.NewClass()
Calling a method throws this exception:
In [4]: nc.important_method()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-09eb0eac244b> in <module>()
----> 1 nc.important_method()
/Users/mike/tmp/reload_test.py in important_method(self)
9
10 for x in range(3):
---> 11 super(NewClass, self).important_method()
TypeError: must be type, not classobj
The class LegacyBase
needs to inherit from object
:
class LegacyBase(object):
def important_method(self):
print 'doing'
class NewClass(LegacyBase):
def important_method(self):
for x in range(3):
super(NewClass, self).important_method()
Now, I can reproduce your problem. Works the first time:
In [5]: nc = reload_test.NewClass()
In [6]: nc.important_method()
doing
doing
doing
After modifying the file in an editor:
class LegacyBase(object):
def important_method(self):
print 'doing'
class NewClass(LegacyBase):
def important_method(self):
for x in range(3):
super(NewClass, self).important_method()
Calling the methods throws an exception:
In [7]: nc.important_method()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-09eb0eac244b> in <module>()
----> 1 nc.important_method()
/Users/mike/tmp/reload_test.py in important_method(self)
9
10 for x in range(3):
---> 11 super(NewClass, self).important_method()
TypeError: super(type, obj): obj must be an instance or subtype of type
Just make a new instance:
In [8]: nc = reload_test.NewClass()
In [9]: nc.important_method()
doing 2
doing 2
doing 2
In practice this means just re-executing the cell that holds nc = reload_test.NewClass()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With