运行时修改Python源码

25 投票
2 回答
26892 浏览
提问于 2025-04-17 03:13

在运行一个应用程序的时候,能不能直接修改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的回答


你有没有尝试过仅仅通过改变一个状态(比如外部配置文件、数据库条目等)来看看能做些什么?

撰写回答