脚本编译后如何在python中重新加载模块?

Jde*_*eep 6 python module reload python-3.x

涉及的基本思想:

我正在尝试制作一个应用程序,学生可以在其中编写与特定问题相关的代码(比如检查数字是否为偶数)然后应用程序通过比较用户代码给出的输出与由应用程序中已经存在的正确代码给出的正确输出。

我正在处理的项目的基本版本:

您可以在其中编写 python 脚本的应用程序(在 tkinter 文本框中)。文本框的内容首先存储在一个test_it.py 文件中。然后该文件由应用程序导入(单击按钮)。test_it.py然后调用中存在的函数以获取代码的输出(由用户)。

问题:

由于我正在“导入” 的内容test_it.py,因此,在应用程序运行时,用户只能测试他的脚本一次。原因是python只会导入test_it.py 文件一次。因此,即使将用户的新脚本保存在 test_it.py 中,它也不会对应用程序可用。

解决方案:

test_it.py每次单击测试脚本的按钮时重新加载

实际问题:

虽然当我从脚本运行应用程序时这完美地工作,但此方法无法用于文件的已编译/可执行版本(.exe)(这是预期的,因为在编译期间所有导入的模块也将被编译,因此修改它们以后就不行了)

问题:

test_it.py即使在编译应用程序后,我也希望重新加载我的文件。


如果您想查看应用程序的工作版本以自行测试。你会在这里找到它。

a_g*_*est 1

即使对于捆绑的应用程序导入也可以按标准方式工作。这意味着每当import遇到 an 时,解释器都会尝试查找相应的模块。您可以test_it.py通过将包含目录附加到sys.path. 它import test_it应该是动态的,例如在函数内部,这样它就不会被 PyInstaller 发现(这样 PyInstaller 就不会尝试将它与应用程序捆绑在一起)。

考虑以下示例脚本,其中应用程序数据存储在托管模块的临时目录中test_it.py

import importlib
import os
import sys
import tempfile

def main():
    with tempfile.TemporaryDirectory() as td:
        f_name = os.path.join(td, 'test_it.py')

        with open(f_name, 'w') as fh:  # write the code
            fh.write('foo = 1')

        sys.path.append(td)  # make available for import
        import test_it
        print(f'{test_it.foo=}')

        with open(f_name, 'w') as fh:  # update the code
            fh.write('foo = 2')

        importlib.reload(test_it)
        print(f'{test_it.foo=}')

main()
Run Code Online (Sandbox Code Playgroud)