Python如何读取和解释源文件?

4 投票
2 回答
2210 浏览
提问于 2025-04-18 16:27

假设我在运行一个Python(2.7,虽然我不确定这是否有影响)的脚本。然后我切换到其他窗口,或者以某种方式回到我的编辑环境。我可以修改这个脚本并保存,但这对仍在运行的脚本没有任何影响。

那么,Python在启动时会把所有源文件完全加载到内存中吗?我觉得这就是Python解释器的工作方式,但这和我对Python解释器的其他理解有些矛盾:我听说过.pyc文件是Python虚拟机的字节码,就像Java中的.class文件一样。不过,同时也有一些(我理解中非常少)Python的实现使用了即时编译技术。

所以我是不是可以这样理解,如果我在脚本运行的时候修改了.py文件,我在重新运行脚本之前是看不到这些修改的,因为在启动时所有需要的.py文件都被编译成了.pyc文件,而简单修改.py文件并不会重新生成.pyc文件?

如果这个理解是正确的,那为什么像我正在处理的这个大程序(大约有6550千字节的源代码,分布在20多个.py文件中)在启动时不会花费很长时间来编译呢?这个程序是怎么这么的呢?


附加信息:

  • 我没有使用第三方模块。所有文件都是本地编写的。主要的源文件相对较小(10 kB),但我主要工作的源文件是65 kB。它也是本地编写的,并且每次启动前都会修改。

2 个回答

2

首先,你的理解是正确的,Python源文件的修改在下次运行之前是不会被解释器看到的。有一些调试系统,通常是为了特定目的而开发的,允许你重新加载模块,但这样会带来一些复杂的问题,比如现有的对象可能还会引用旧模块中的代码,这样就会变得很麻烦。

大型程序启动得很快的原因是,解释器会尝试为每个导入的.py文件创建一个.pyc文件,前提是要么没有对应的.pyc文件,要么.py文件是新的。.pyc文件实际上是程序编译成字节码的结果,所以加载起来相对较快。

至于即时编译(JIT),你可能是在想PyPy这个实现,它是用Python写的,并且有多个不同语言的后端。它在对执行速度要求高的Python 2环境中越来越多地被使用,但与我们熟悉的CPython相比,它还有很长的路要走。

4

Python会把主脚本加载到内存中,然后把它编译成字节码并运行。如果你在这个过程中修改了源文件,实际上并不会影响到字节码。

如果你是把脚本当作主脚本来运行(也就是说像这样调用它:python myfile.py),那么当脚本结束时,字节码会被丢弃。

但是如果你是导入这个脚本的话,字节码会被写入磁盘,形成一个.pyc文件。下次再导入时,这个文件不会被重新编译,除非你修改了对应的.py文件。

你的大约6.5 MB的程序由许多模块组成,这些模块都是由(可能很小的)主脚本导入的,所以每次运行时只需要编译主脚本。其他的文件都会有它们的.pyc文件准备好运行。

撰写回答