重新加载当前运行的python脚本

时间:2015-04-30 06:35:16

标签: python debugging

在python中,有一个重装方法来重新加载导入的模块,但是有一种方法可以重新加载当前运行的脚本而不重新启动它,这对于调试脚本和在脚本是的时候更改代码非常有用。运行。在visual basic中,我记得类似的功能被称为"应用代码更改",但我需要类似于函数调用的功能,如" refresh()"这将立即应用代码更改。

当脚本中的独立函数被修改并且我们需要立即应用代码更改而不重新启动脚本时,这将顺利运行。

Inshort将:

reload(self) 

工作?

6 个答案:

答案 0 :(得分:2)

reload(self)不起作用,因为reload()适用于模块,而不适用于类的实例。你想要的是你的主应用程序外部的一些逻辑,它检查是否必须重新加载。您必须考虑在重新加载时重新创建应用程序状态所需的内容。

这方面的一些暗示: Guido van Rossum曾写过:xreload.py;它比reload()稍微多一点你需要一个循环,每隔x秒检查一次变化并应用它。

还要看看基本上这样做的livecoding编辑:我把这个项目误认为是其他东西(我现在没找到),抱歉。

也许this SO question会帮助你

答案 1 :(得分:0)

也许你的意思是这样的:

import pdb
import importlib
from os.path import basename

def function():
    print("hello world")

if __name__ == "__main__":
    # import this module, but not as __main__ so everything other than this
    # if statement is executed
    mainmodname = basename(__file__)[:-3]
    module = importlib.import_module(mainmodname)

    while True:
        # reload the module to check for changes
        importlib.reload(module)
        # update the globals of __main__ with the any new or changed 
        # functions or classes in the reloaded module
        globals().update(vars(module))
        function()
        pdb.set_trace()

运行代码,然后更改function的内容并在提示符处输入c以运行循环的下一次迭代。

答案 2 :(得分:0)

test.py

class Test(object):

    def getTest(self):
       return 'test1'

testReload.py

from test import Test
t = Test()
print t.getTest()

# change return value (test.py)

import importlib
module = importlib.import_module(Test.__module__)
reload(module)
from test import Test
t = Test()
print t.getTest()

答案 3 :(得分:0)

简介

reload用于导入的模块。 Documentation for reload建议不要重新加载__main__

不建议重新加载sys__main__builtins和其他关键模块。

要在脚本上实现类似的行为,您将需要重新执行脚本。对于普通脚本,这还将重置全局状态。 我提出了解决方案。

注意

我提出的解决方案非常强大,并且仅应用于您信任的代码。自动执行来自未知来源的代码可能会导致痛苦。 Python不是soapbox编写不安全代码的好环境。

解决方案

要以编程方式从另一个脚本执行python脚本,您只需要内置功能opencompileexec

这是一个示例函数,它将重新执行它所在的脚本:

def refresh():
    with open(__file__) as fo:
        source_code = fo.read()
        byte_code = compile(source_code, __file__, "exec")
        exec(byte_code)

在通常情况下,以上内容还将重置您可能具有的所有全局变量。如果您希望保留这些变量,则应检查天气或未设置这些变量。这可以通过覆盖NameError异常的try-except块来完成。但这可能很乏味,所以我建议使用标志变量。

以下是使用flag变量的示例:

in_main = __name__ == "__main__"
first_run = "flag" not in globals()

if in_main and first_run:
    flag = True

答案 4 :(得分:0)

这些答案都没有适合我的工作,所以我把一些非常凌乱且非常非 Python 的东西放在一起来自己完成这项工作。即使在运行它几个星期之后,我还是发现了小问题并修复了它们。一个问题是您的 PWD/CWD 是否发生变化。

警告这是非常丑陋的代码。也许有人会把它弄得很漂亮,但它确实有效。

它不仅创建了一个 refresh() 函数,该函数以某种方式正确地重新加载您的脚本,以便任何异常都能正确显示,而且它还为以前加载的脚本创建了 refresh_<scriptname> 函数,以防万一您需要重新加载那些。

接下来我可能会添加一个 require 部分,以便脚本可以重新加载其他脚本——但我不是要在这里制作 node.js。

首先,您需要在要刷新的任何脚本中插入的“单行”。

with open(os.path.dirname(__file__) + os.sep + 'refresh.py', 'r') as f:    \
    exec(compile(f.read().replace('__BASE__',                              \
        os.path.basename(__file__).replace('.py', '')).replace('__FILE__', \
            __file__), __file__, 'exec'))

其次,实际的刷新函数应该保存在同一目录中的 refresh.py 中。 (看,已经有改进的余地了)。

def refresh(filepath = __file__, _globals = None, _locals = None):
    print("Reading {}...".format(filepath))
    if _globals is None:
        _globals = globals()
    _globals.update({
        "__file__": filepath,
        "__name__": "__main__",
    })
    with open(filepath, 'rb') as file:
        exec(compile(file.read(), filepath, 'exec'), _globals, _locals)

def refresh___BASE__():
    refresh("__FILE__")

使用 Python 2.7 和 3 进行测试。

答案 5 :(得分:-1)

如果您在交互式会话中运行,则可以使用ipython autoreload

  

autoreload在进入IPython提示符下输入的代码执行之前自动重新加载模块。

当然这也适用于模块级别,因此您可以执行以下操作:

>>>import myscript
>>>myscript.main()
*do some changes in myscript.py*
>>>myscript.main() #is now changed