我理解“.pyc”文件是纯文本“.py”文件的编译版本,在运行时创建以使程序运行得更快。但是我发现了一些事情:
rm *.pyc
)后,程序行为有时会发生变化。这表明他们没有在更新“.py”时编译。问题:
答案 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?。