Изменение источника python во время работы
Можно ли изменить исходный файл python во время запуска приложения и немедленно ли это изменить в приложении?
Скажем, у меня есть файл foo.py с классом Foo. В другом модуле я вызываю функции в действии пользователя Foo. Теперь я хотел бы изменить источник Foo без перезапуска приложения и на следующем входе пользователя посмотреть результаты нового кода.
Возможно ли это?
Ответы
Ответ 1
Да, но это плохо советовало — код, который сам изменяется (хотя и необходим в некоторых случаях), как правило, трудно отлаживать. Вы ищете метод reload
. Способ, которым вы могли бы работать, состоял в том, чтобы изменить исходный файл, а затем вызвать перезагрузку модуля, а затем повторить.
У вас есть возможность повторно назначать и изменять код внутри самого приложения — то, что не подвергает риску условия гонки, и это также обеспечит более последовательную и проверяемую среду. Например, я бы пересчитал Ignacio Vazquez-Abrams
answer.
Вы пытались понять, что вам удалось, просто изменив состояние (внешний файл конфигурации, запись в базу данных и т.д.).
Ответ 2
Следующий модуль, вероятно, может изменить все, что вам нужно, а не использовать его, кроме как гасить:)
Обратите внимание, что он не изменит ваш источник, что, вероятно, будет катастрофой, особенно если вы сделаете ошибку кодирования. "Безопасный" вариант - играть с byteplay
http://wiki.python.org/moin/ByteplayDoc
Хорошо, теперь играй! Скажем, мы хотим изменить функцию, чтобы напечатать ее аргументы в обратном порядке. Для этого мы добавим код операции ROT_TWO после того, как два аргумента были загружены в стек. Посмотрите, насколько это просто:
>>> from byteplay import *
>>> from pprint import pprint
>>> def f(a, b):
... print (a, b)
...
>>> f(3, 5)
(3, 5)
>>> c = Code.from_code(f.func_code)
>>> c.code[3:3] = [(ROT_TWO, None)]
>>> f.func_code = c.to_code()
>>> f(3, 5)
(5, 3)
>>> f(3, 5)
(5, 3)
Если вы используете определенный набор параметров, но хотите сохранить один и тот же вызов функции, вы также можете сделать что-то вроде следующего
class Foo(object):
def fn(self):
pass
def op1(self):
print "HELLO"
#etc
>>> a = Foo()
>>> a.fn()
>>> a.fn = a.op1
>>> a.fn()
HELLO