1.修改“py”文件后,程序行为会发生变化。这表明“py”文件已编译或至少经过某种哈希处理或比较时间戳,以判断它们是否应重新编译。
2.删除所有“.pyc”文件(rm * .pyc)有时会改变程序行为。这表明它们没有在“ .py”更新时进行编译。
问题:
1.它们如何决定何时进行编译?
2.有没有办法确保它们在开发期间进行更严格的检查?
.pyc
文件只有在被其他脚本导入时才会被创建(可能会被覆盖)。如果进行了导入,Python将检查.pyc
文件的内部时间戳是否比相应的.py
文件更旧。 如果是,则加载.pyc
; 如果不是或者.pyc
文件还不存在,则Python将编译.py
文件成.pyc
并加载它。
"更严格的检查"是什么意思?
.pyc
文件的时间戳必须比相应的.py
文件的时间戳旧,才会触发重新编译。 - Tim Pietzcker.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文件。有关更多详细信息,请参见如何避免 .pyc 文件?。
另请参阅:如何从项目中删除所有 .pyc 文件?
__init__.py
文件的文件夹)时......那将是一个包,而不是一个模块。 - bgrant__init__.pyc
文件会保留下来。为什么呢?因为包是一个目录,删除包意味着删除目录,因此不会剩余任何文件。 - Piotr Dobrogost.pyc
问题就是其中之一,同时还有:依赖操作系统和实用程序补丁级别、 .so
文件、配置文件、其他 Python 库(如果你没有在虚拟环境中运行)以及晦涩的环境变量等。为了彻底找到所有此类问题,你需要在 Git 存储库中创建一个干净的副本或者作为包发布到 PyPi 风格服务器,并在新的虚拟机上进行完全克隆或安装。其中一些潜在问题使得这个 .pyc
问题相形见绌。 - Chris Johnson
rm *.pyc
命令删除 .pyc 文件,因为它无法删除嵌套文件夹中的 .pyc 文件。建议使用find . -name '*.pyc' -delete
命令来代替。 - Zags