运行时修改Python源码
在运行一个应用程序的时候,能不能直接修改Python源文件,并且让这些修改立刻在应用程序中生效呢?
比如说,我有一个叫foo.py的文件,里面定义了一个类Foo。在其他模块中,我根据用户的操作来调用Foo里的函数。现在,我想在不重启应用程序的情况下,修改Foo的代码,然后在下次用户输入时看到新代码的效果。
这样做可以吗?
2 个回答
9
下面这个模块可能可以帮你改变你需要的东西,不过除了玩玩以外,使用它并不是个好主意 : )
要注意的是,它不会改变你的源代码,毕竟那样可能会出大问题,特别是你如果写错了代码。更安全的选择是使用 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
12
是的,不过这样做并不太好——自我修改的代码(虽然在某些情况下是必要的)通常很难调试。你需要找的是reload
这个方法。要让它工作,你需要先修改源文件,然后对模块调用reload,再重复这个过程。
你也可以选择在应用程序内部重新分配和修改代码——这样做不会引发竞争条件,并且能让环境更加一致和可测试。举个例子,我推荐Ignacio Vazquez-Abrams
的回答。
你有没有尝试过仅仅通过改变一个状态(比如外部配置文件、数据库条目等)来看看能做些什么?