只有在.pyc文件过期时才编译吗?

后端开发 2026-07-09

有没有办法把一个.py脚本编译成.pyc,但只有在它缺失或落后于 the.py 文件时才进行编译?

我想在必要时编译该文件,然后在Python内部运行它,exec() 能运行.pyc文件吗?

import py_compile
py_compile.compile('Child.py')
exec(open('Child.py').read())

这可行,但每次运行都会重新编译该文件。

在jsbueno的注释基础上——一个更全面的示例:

Parent.py

def main():
    class cParent:
        test = "test"

    oParent = cParent()

    print("In parent 1")
    import py_compile
    py_compile.compile('Child1.py')
    exec(open('Child1.py').read(), {}, {"oParent":oParent})
    print("In parent 2")

Child1.py

print("In child 1")
print(oParent.test)
print("In child 2")

解决方案

你得到的结果是什么?因为Python对 PYC文件的默认编译启发式已经做到这一点:如果文件过时就会重新构建。此外,这有点复杂——可以复现这种行为,但理想情况下,为了覆盖所有边缘情况,你需要跟踪源代码哈希、当前环境的Python版本与体系结构等……所有这些都内置在语言的导入机制中。

例外的是你调用的主Python文件:如果你不是把应用打包成一个包,而是把大量应用程序放在一个大的 ".py" 文件中,直接用 "python myapp.py" 调用——那么这个文件每次都会被重新编译。

所以,回到你的问题——问题在于你显式地编译了你的文件;如果你只是导入它,并调用其中一个可用作入口点的函数,而不是通过exec,那么你就能受益于上面的启发式规则。

import Child

Child.entry()

并在 Child.py 内,将代码重新排列,使模块的顶层不执行代码,而是在调用某个函数时再执行——然后编写这个 entry 函数来运行该代码:

Child.py - 之前

my()
spread_Apart()
with_side_effects_on_toplevel()
code()

变为:

Child.py - 之后:

def entry():
   my()
   spread_Apart()
   with_side_effects_on_toplevel()
   code()

if __name__ == "__main__":
    # this if guard ensures the previous behavior is unchanged
    # when the file is called directly from CLI
    entry()
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章