什么时候.pyc文件刷新?

时间:2013-04-05 17:05:59

标签: python python-internals pyc

我理解“.pyc”文件是纯文本“.py”文件的编译版本,在运行时创建以使程序运行得更快。但是我发现了一些事情:

  1. 修改“py”文件后,程序行为会发生变化。这表明“py”文件已编译或至少通过某种散列过程或比较时间戳来判断是否应重新编译它们。
  2. 删除所有“.pyc”文件(rm *.pyc)后,程序行为有时会发生变化。这表明他们没有在更新“.py”时编译。
  3. 问题:

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

2 个答案:

答案 0 :(得分:69)

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

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

答案 1 :(得分:28)

每当导入相应的代码元素时生成

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

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

首先,您最终可以推送仅适用于您的计算机而不是其他人的代码。如果您对已删除的文件有悬空引用,那么如果您不手动删除相关的.pyc文件,这些文件仍可在本地使用,因为.pyc文件可用于导入。这与以下事实相混淆:正确配置的版本控制系统只会将.py文件推送到中央存储库,而不是.pyc文件,这意味着您的代码可以通过“导入测试”(一切导入正常)就好了而不是在别人的电脑上工作。

其次,如果将软件包转换为模块,则可能会遇到一些非常糟糕的错误。将包(具有__init__.py文件的文件夹)转换为模块(.py文件)时,保留曾经表示该包的.pyc文件。特别是,__init__.pyc仍然存在。所以,如果你的包foo包含一些无关紧要的代码,那么稍后删除该包并创建一个带有一些函数def bar(): pass的文件foo.py并运行:

from foo import bar

你得到:

ImportError: cannot import name bar

因为python仍在使用foo包中的旧.pyc文件,其中没有一个定义bar。这在Web服务器上尤其成问题,因为.pyc文件会导致完全正常运行的代码崩溃。

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

find . -name '*.pyc' -delete

此外,从python 2.6开始,您可以使用-B标志运行python以不使用.pyc文件。有关详细信息,请参阅How to avoid .pyc files?

另请参阅:How do I remove all .pyc files from a project?