How to reload the code of a method of class object in Python?

一曲冷凌霜 提交于 2019-11-28 09:07:06

问题


I'm find a way to reload the method of a class object at runtime,here is the example: I have define a class A firstly which lies on the file test.py.

class A:
    def __init_(self):
        pass
    def Message(self):
        print "1"

then I start Python shell in the linux, and execute the following code:

>>> from test import A
>>> a = A()
>>> a.Message()
1

Now I vi the test.py in the fly, and change the method "Message":

class A:
    def __init_(self):
        pass
    def Message(self):
        print "2"

but when I execute the a.Message() in the Python shell, the result is always the "1" and not "2"

How I write the code to make the object 'a.Message' to execute the updated code.

Thank you very much!

chu


回答1:


To relaod your module in the interactive interpreter, you can use

import test
reload(test)
from test import A

But this won't affect instance of A which already exist -- they will still be of the old type A, hence having the old method. I think it is not possible to change existing instances, nor do I think it is a good idea.

By the way, I would recommend using IPython for code testing. It facilitates recursive reload using the %reload magic, and (even more useful) the %run magic to test modules.




回答2:


You have to reload your module from the fresh code, get the class and assign it back to the instance:

import sys
def update_class(instance):
  cls=instance.__class__
  modname=cls.__module__
  del sys.modules[modname]
  module=__import__(modname)
  instance.__class__=getattr(module,cls.__name__)

While developing and updating the code you could use the same trick to define instances that reload their class anytime they are used.

import sys

class ObjDebug(object):
  def __getattribute__(self,k):
    ga=object.__getattribute__
    sa=object.__setattr__
    cls=ga(self,'__class__')
    modname=cls.__module__ 
    mod=__import__(modname)
    del sys.modules[modname]
    reload(mod)
    sa(self,'__class__',getattr(mod,cls.__name__))
    return ga(self,k)

class A(ObjDebug):
   pass

a=A()

If you edit the code of A to add a method, then you can use it without instantiating again a.

Actually del sys.modules[modname] seems to create nasty bugs for which some symbols becomes None objects from one line to the other. (not understood why)




回答3:


I've just spend a while trying to solve this issue myself and ended up with a slightly different solution to the others suggested here. I've put it in a gist with plenty of comments, but as is the SO way I'll give a brief explantion here:

Rather than modify individual instances of an old version of a class, or copy them into new instances of the new class, the idea is to set the methods of the old class (i.e. the attributes of the class itself not the instances of the class) to be the updated methods from the new class. It also takes care of chaining back over multiple versions of the class.



来源:https://stackoverflow.com/questions/4670586/how-to-reload-the-code-of-a-method-of-class-object-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!