在运行时更改Python源码

25
在运行应用程序时更改Python源文件并立即反映在应用程序中是否可能?比如说,我有一个包含类Foo的foo.py文件。在另一个模块中,我在用户操作时调用Foo上的函数。现在,我想在不重启应用程序的情况下更改Foo的源代码,并在下一次用户输入时看到新代码的结果。这是否可能?

8
您为什么想要做这件事?这有什么用途? - jhocking
https://dev59.com/knRC5IYBdhLWcg3wAcXU - jterrace
2
@jhocking:只是在懒得写正式测试的时候测试一些东西。 - Miroslav Zadravec
5
@Miroslav,最懒惰的做法是不写测试。试图用一些奇怪、疯狂的方法来完成测试只会引入错误(静默或其他)并使你的测试更加困难甚至出错。请务必写好测试。 - Mike Graham
3
@MikeGraham 这是一个非常好的练习,可以帮助学习语言的工作原理。一旦理解了它的工作原理,就不再感觉奇怪和疯狂了。 - Evgeni Sergeev
2个回答

12

是的,但这并不被推荐——代码更改自身(尽管在某些情况下必要)通常很难调试。你需要使用reload方法。你需要修改源文件,然后调用模块中的reload方法,然后重复这个过程。

你也可以在应用程序内部重新分配和修改代码——这不会有竞争条件的风险,同时还可以提供更一致和可测试的环境。例如,我推荐阅读Ignacio Vazquez-Abrams的答案


你尝试通过仅更改状态(外部配置文件、数据库条目等)来解决问题了吗?


2
这更像是毫无建设性的错误建议。使用reload基本上存在缺陷,并且不是 OP 实际问题的正确工具。 - Mike Graham

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接