.pyc文件什么时候刷新?


91

我知道“ .pyc”文件是纯文本“ .py”文件的编译版本,是在运行时创建的,以使程序运行更快。但是我观察到了一些事情:

  1. 修改“ py”文件后,程序行为会更改。这表明“ py”文件已编译或至少经过某种哈希处理或比较时间戳,以便确定是否应重新编译它们。
  2. 删除所有“ .pyc”文件(rm *.pyc)后,有时程序行为也会改变。这表明它们不是在更新“ .py”时被编译的。

问题:

  • 他们如何决定何时编译?
  • 有没有办法确保他们在开发过程中进行更严格的检查?

14
当心使用删除.pyc文件rm *.pyc。这不会删除嵌套文件夹中的.pyc文件。使用find . -name '*.pyc' -delete替代
牛头犬

6
可能有一个关于您的问题的注释:从'.pyc'或'.pyo'文件中读取程序比从'.py'文件中读取程序运行得更快。关于“ .pyc”或“ .pyo”文件,唯一更快的是它们的加载速度。链接
玛姬2015年

@maggie加载和执行时间有什么区别?
丹尼尔·史普林格

3
@Dani加载是读取然后编译程序所花费的时间。执行时间是程序实际运行时的时间,它发生在加载之后。如果您想成为技术人员,则时间类型为加载时间,编译时间,链接时间和执行时间。制作.pyc消除了编译时部分。
埃里克·克莱恩

@EricKlien谢谢男人
Daniel Springer

Answers:


78

.pyc文件被创建(并可能覆盖)仅当蟒蛇文件是否已被其他脚本导入。如果调用了导入,Python将检查.pyc文件的内部时间戳是否不早于相应的.py文件。如果是,它将加载.pyc;。如果.pyc不存在或尚不存在,Python 会将.py文件编译为.pyc并加载。

“严格检查”是什么意思?


3
我能够解决的问题rm *.pyc。我知道如果我强制重新创建所有文件,则某些问题已修复,这表明这些文件本身并未被重新编译。我想如果他们确实使用时间戳,则没有办法使这种行为更严格,但是问题仍然存在。
亚伦·希夫

13
这不是很正确。时间戳不需要匹配(通常不需要)。该.pyc的时间戳必须是年龄较大的比相应.py的时间戳来触发重新编译。
蒂姆·皮茨克

4
@Aaron,您是否有可能更改.py文件,并在使它们变旧的过程中(例如,通过使用保留“修改时间”的操作从另一个目录复制它们)?
greggo 2013年

1
@greggo,我正在使用git并从存储库中进行更新,所以可以。可以做到的。谢谢。
亚伦·谢夫

1
很高兴知道。那更正答案呢?
Piotr Dobrogost

29

每当导入相应的代码元素时都会生成.pyc文件,如果相应的代码文件已更新,则将更新.pyc文件。如果.pyc文件被删除,它们将自动重新生成。但是,当删除相应的代码文件时,不会自动删除它们。

在文件级重构期间,这可能会导致一些非常有趣的错误。

首先,您最终可能会推送仅在您的计算机上运行的代码,而在其他计算机上则无法运行。如果悬吊了对已删除文件的引用,则在不手动删除相关.pyc文件的情况下,这些引用仍将在本地运行,因为.pyc文件可以在导入中使用。再加上这样的事实,即正确配置的版本控制系统只会将.py文件推送到中央存储库,而不会将.pyc文件推送到中央存储库,这意味着您的代码可以顺利通过“导入测试”(一切都可以导入)在其他人的计算机上工作。

其次,如果将包转换为模块,可能会遇到一些非常可怕的错误。将包(带有文件的__init__.py文件夹)转换为模块(.py文件)时,曾经表示该包的.pyc文件保留。特别是__init__.pyc遗骸。因此,如果您的软件包foo包含无关紧要的代码,请稍后删除该软件包并创建具有某些功能的文件foo.py def bar(): pass并运行:

from foo import bar

你得到:

ImportError: cannot import name bar

因为python仍在使用foo包中的旧.pyc文件,但都没有定义bar。这在Web服务器上尤其成问题,在Web服务器上,.pyc文件可能会破坏所有正常运行的代码。

由于这两个原因(可能还有其他两个原因),您的部署代码和测试代码应删除.pyc文件,例如使用以下bash行:

find . -name '*.pyc' -delete

另外,从python 2.6开始,您可以运行带有-B标记的python,以不使用.pyc文件。请参阅如何避免.pyc文件?更多细节。

另请参阅:如何从项目中删除所有.pyc文件?


“当转换模块(带有文件的__init__.py文件夹)时...”。那将是一个包装,而不是一个模块。
罗伯特·大卫·格兰特

2
特别是__init__.pyc遗骸。- 怎么会?由于软件包是目录,因此删除软件包意味着删除目录,因此没有文件了……
Piotr Dobrogost

3
@PiotrDobrogost正确管理的源代码控制涉及不将pyc文件检入源代码。因此,尽管您可以在本地副本中删除该文件夹(包括pyc文件),但不会对其他执行git pull的人删除该文件夹。如果您的部署还涉及git pull,这可能会使您的服务器崩溃。
Zags

有许多原因不信任您的开发环境来代表您的代码部署位置。这个.pyc问题也是一个原因,原因是:对OS和实用程序补丁程序级别,.so文件,配置文件,其他Python库(如果您不在虚拟环境中运行)的隐藏依赖性,模糊的环境变量...等等。为了彻底查找所有此类问题,您需要在git repo中制作代码的完整副本,或将其作为软件包发布到PyPi样式服务器中,然后在新的VM上进行完整的克隆或设置。.pyc相比之下,其中一些潜在问题使此问题显得苍白。
克里斯·约翰逊
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.