Ограничения перезагрузки скрученного кода - PullRequest
4 голосов
/ 30 марта 2012

Я создаю сервер XML-RPC, используя Twisted, который периодически проверяет, изменились ли временные метки его исходных файлов, и перезагружает их, используя rebuild.

from twisted.python.rebuild import rebuild

rebuild(mymodule)

Функции, предоставляемые сервером, прекрасно перезагружаются, но в другом активном классе протокола, который вызывает функции обратного вызова для того же класса mymodule, но они не используют перезагруженную версию функций. Этот протокол просто имеет dict с обычными функциями в качестве значений.

Я нашел этот класс mixin, который предназначен для ограничения rebuild.

http://twistedmatrix.com/documents/current/api/twisted.python.rebuild.Sensitive.html

Как сделать так, чтобы в моих обратных вызовах использовался обновленный код?

1 Ответ

2 голосов
/ 01 апреля 2012

Вы правы;это ограничение twisted.python.rebuild.Он обновляет атрибут __class__ существующих экземпляров и импортированных функций и классов.

Один из способов справиться с этим - просто отправить патч Twisted , исправляющий rebuildдля этого случая.

Однако, если вы хотите использовать Sensitive по прямому назначению, вы также можете реализовать свой класс удержания обратного вызова для работы с rebuild в текущих версиях Twisted.В следующих примерах показано, как использовать все три метода соответствующего класса для обновления словаря обратных вызовов, указывающих на функции.Обратите внимание, что даже без теста if needRebuildUpdate... прямой вызов x() всегда даст самую последнюю версию.

from twisted.python.rebuild import rebuild, Sensitive
from twisted.python.filepath import FilePath

p = FilePath("mymodule.py")
def clearcache():
    bytecode = p.sibling("mymodule.pyc")
    if bytecode.exists():
        bytecode.remove()
clearcache()
p.setContent("def x(): return 1")
import mymodule
from mymodule import x
p.setContent("def x(): return 2")

class Something(Sensitive, object):
    def __init__(self):
        self.stuff = {"something": x}
    def invoke(self):
        if self.needRebuildUpdate():
            for key in list(self.stuff):
                self.stuff[key] = self.latestVersionOf(self.stuff[key])
            self.rebuildUpToDate()
        return self.stuff["something"]()

def test():
    print s.invoke()
    print x()

s = Something()
test()

clearcache()
rebuild(mymodule)

test()
...