2

我正在尝试将代码作为模块加载,然后在 Python 中以编程方式重新加载相同的模块但不同的代码:

import imp

a = """
def test():
    print "Hello from a"
"""

b = """
def test():
    print "Hello from b"
"""


for code in [a, b]:
    with open('user.py', 'wb') as f:
        f.write(code)
    mod = imp.load_source('user', 'user.py')
    getattr(mod, "test")()

预期输出:

Hello from a
Hello from b

实际输出:

Hello from a
Hello from a

显然我对它如何工作的理解是不正确的,但我似乎无法弄清楚我的错误。

我可以让它工作的唯一方法是在我在文件中编写代码之前删除生成的 .pyc 文件f。有没有更好的办法?

4

3 回答 3

3

如果您要从字符串或文件中动态加载代码,最好使用exec/execfile而不是import. import适用于静态或很少更改的文件。

如果您仍想使用imp.load_source,请注意以下警告:

请注意,如果存在正确匹配的字节编译文件(后缀为 .pyc 或 .pyo),则将使用它而不是解析给定的源文件。

“正确匹配”意味着编译文件的版本与解释器匹配并且时间戳匹配。正如 Tim 所指出的,如果您连续两次快速写入文件,则时间戳可能不会更改,并且 .pyc 仍将被视为有效。

于 2012-09-19T06:39:22.157 回答
2

可能不是因为您的.pyc文件的时间戳(精确到一秒)不会早于您新写入.py文件的时间戳;因此imp将使用“当前”.pyc文件,除非您先将其删除。

或者,您可以尝试在重新加载模块之前等待两秒钟。

于 2012-09-19T06:38:00.467 回答
0

每当您运行或导入 python 文件、模块或包时,解释器将检查是否存在与 py 文件版本匹配的 pyc 文件。如果是,它将使用 pyc 文件,否则将编译 py 文件并覆盖旧的 pyc 文件。如果 pyc 匹配 py 文件的版本是基于文件日期的。由于您没有保存文件 (f),因此 Python 无法识别它同时发生了某些变化。因此,如果您希望您的方法起作用,则需要在每次循环后保存文件。

于 2012-09-19T07:02:17.847 回答