__pycache__是什么?

1066
据我所了解,缓存是一种相似文件的加密文件。
那么我们应该怎么处理 __pycache__ 文件夹呢?它是我们给他人的源代码吗?还是只是我的输入数据?为什么这个文件夹总是会被创建?

48
“这是我们给人们的代替我们源代码的东西吗?”- 不是,你会把源代码放在一个易于安装的包中给他们使用。 - Lennart Regebro
166
还没有人提到,但是你对缓存的定义很奇怪。缓存就是一种组件,用于存储数据,以便未来请求该数据时可以更快地提供服务。 - Ricardo Magalhães Cruz
10
参见:https://www.python.org/dev/peps/pep-3147/ - Mr_and_Mrs_D
7
Python 3.8 起,您可以使用一个环境变量来更改位置以避免烦人的缓存目录:https://stackoverflow.com/a/57414308/1612318。 - Rotareti
6
缓存是为了在需要再次使用某些内容时保留其副本,以避免返回原始位置获取它。它旨在比访问原始位置更快。之所以更快,是因为它不需要预处理或编译信息,或者是因为它采用了更快的存储方式,例如RAM中的磁盘缓存或本地磁盘上的Web缓存。缓存本质上并非加密(尽管有时可能会是),而且它并不总是“类似文件的文件” - 它可以是一个文件、一堆文件、一块RAM等。 - rjmunro
3
将搜索词 PYTHONPYCACHEPREFIX 放在这里 - 有关更多信息,请参见 @Rotareti 的评论 - bers
11个回答

924
当你在Python中运行程序时,解释器首先将其编译成字节码(这是一个简化),并将其存储在__pycache__文件夹中。如果你查看其中的内容,你会发现一堆文件共享你项目文件夹中.py文件的名称,只是它们的扩展名分别为.pyc或.pyo。这些分别是你程序文件的字节码编译和优化字节码编译版本。
作为程序员,你大多可以忽略它...它只是使你的程序启动更快。当你的脚本发生变化时,它们将被重新编译,如果你删除文件或整个文件夹并再次运行你的程序,它们将重新出现(除非你特别禁止该行为)。
当你发送代码给其他人时,常见的做法是删除那个文件夹,但这并不重要,你可以选择删除或不删除。当你使用版本控制(git)时,该文件夹通常列在忽略文件(.gitignore)中,并因此不包括在内。
如果你正在使用CPython(这是最常用的,因为它是参考实现),而你不想要那个文件夹,那么你可以通过以-B标志启动解释器来禁止它,例如:
python -B foo.py

如tcaswell所指出的,另一种选择是将环境变量 PYTHONDONTWRITEBYTECODE 设置为任何值(根据Python的man页面,任何“非空字符串”均可)。


73
您可以添加环境变量 PYTHONDONTWRITEBYTECODE=<任意值> 来永久禁用它。 - Mark Tolonen
18
请澄清一下,这只适用于Python 3,对吗? - Joe J
16
是的,我认为这是正确的。如果我没记错,python2会将编译后的文件放在与原始文件相同的目录中。 - scott_fakename
44
重要说明:如果.py文件不存在,将使用缓存的.pyc文件。实际上,只有在删除(或重命名)模块时才会发生这种情况,因此这不是常见情况,但如果一些东西一直存在,而且你已经想了很久也无法解决,那么运行“find . -name *.pyc | xargs rm”命令可能是一个好的第一反应。 - yacc143
48
find . -name '*.pyc' -delete 这个命令会查找当前目录及其子目录中所有扩展名为 .pyc 的文件并将其删除。是的,find 命令有一个标志用于删除找到的文件,因此您不必使用任何 xargs 技巧。 - vlad-ardelean
显示剩余7条评论

241

__pycache__ 是一个文件夹,其中包含编译好并准备执行的Python 3 字节码

我不建议经常费力地删除这些文件或在开发过程中抑制创建,因为这会浪费你的时间。只需准备好一个递归命令(见下文),在需要清理字节码时使用,因为在某些特殊情况下字节码可能会变得陈旧(请参阅注释)。

Python 程序员通常忽略字节码。实际上,在 .gitignore 文件中看到 __pycache__*.pyc 是很常见的。字节码不适用于分发,并且可以使用 dis 模块进行反汇编。


如果您正在使用OS X,则可以从项目的根目录运行以下命令,轻松隐藏项目中的所有这些文件夹。

find . -name '__pycache__' -exec chflags hidden {} \;

__pycache__ 替换为 *.pyc 以适用于Python 2。

这将在所有这些目录(.pyc文件)上设置一个标志,告诉 Finder/Textmate 2 不要将它们包含在列表中。重要的是,字节码仍然存在,只是被隐藏了。

如果您创建了新模块并希望隐藏新的字节码,或者删除了隐藏的字节码文件,请重新运行该命令。


在Windows中,等效的命令可能是(未经测试,欢迎批处理脚本):

dir * /s/b | findstr __pycache__ | attrib +h +s +r

这与使用右键隐藏文件夹来浏览项目相同...


在运行单元测试时(更多内容请见评论),删除*.pyc文件和__pycache__文件夹确实是有用的。我在~/.bash_profile中使用以下行,只需要运行cl即可在需要时清理。

alias cpy='find . -name "__pycache__" -delete'
alias cpc='find . -name "*.pyc"       -delete'
...
alias cl='cpy && cpc && ...'

最近更多的是

# pip install pyclean
pyclean .

2
@DoTheEvo:它根本没有被创建,因此下一次加载模块时不会加快速度。不会引发任何错误。 - Petr Viktorin
21
这不是一个好的回答。提问者想知道这些文件有什么用途。而这个回答说“不要担心”,然后让它们消失了。 - interestinglythere
63
请务必不要删除这些内容:这并不是毫无意义的。在许多情况下,Python会快乐地不检测文件更改,并运行缓存文件,这会让你感到非常恼火,因为它仍然无法识别不存在的调用而失败,让你感到困惑。特别是在测试框架中,默认启用pycache是最糟糕的。 - Mike 'Pomax' Kamermans
1
什么情况下?在过去的10年中,每当我怀疑字节码是问题所在时,实际上它总是出现在其他地方。 - fmalina
3
我不同意“不要费心删除这些文件”的建议 - 我已经看到很多次这样的建议,最近是由Kenneth Reitz的“How To Python”(“字节码技巧”)推荐的。 - Louis Maddox
显示剩余8条评论

87

当你使用代码行:

__pycache__

时,会创建一个__pycache__文件夹。

import file_name

或者尝试从您创建的另一个文件中获取信息。这会使第二次运行程序时打开其他文件更快一些。


41

来自3.7+文档的更新答案:

为了加快模块加载速度,Python会将每个模块的已编译版本缓存到__pycache__目录中,使用module.version.pyc的名称进行标识。这里的version指的是编译文件的格式编码,通常包含Python版本号。例如,在CPython 3.3版本中,spam.py的编译版本将被缓存为__pycache__/spam.cpython-33.pyc。此命名约定允许不同版本和不同Python版本的编译模块共存。

来源:https://docs.python.org/zh-cn/3/tutorial/modules.html#compiled-python-files

也就是说,这个目录是由Python生成的,存在的目的是加快程序的运行速度。它不应该提交到源代码控制,并且应该与本地源代码和平共处。


__pycache__是一个包含字节码缓存文件的目录,这些文件是Python自动生成的,即编译的Python文件(.pyc)。你可能会想知道,为什么Python(一种“解释型”语言)需要任何编译文件。这个SO问题回答了这个问题(其中这个答案绝对值得一读)。

Python文档详细介绍了它的工作原理和存在的原因:


这是我需要知道的主要部分:“它不应该提交到源代码控制中”。谢谢!我现在将__pycache__/添加到我的存储库根目录下的.gitignore文件中,以使Git忽略所有这些自动生成的__pycache__目录! - Gabriel Staples

11

当你导入一个模块时,

import file_name

Python会将编译后的字节码存储在__pycache__目录中,以便未来的导入可以直接使用它,而不必重新解析和编译源代码。

仅当文件被导入时才会这样做,运行脚本则不会。

(早期版本使用.py文件一起散落在同一个目录下的缓存字节码文件(.pyc),但从Python 3开始,它们被移动到了一个子目录中,使事情变得更加整洁。)

PYTHONDONTWRITEBYTECODE ---> 如果将其设置为非空字符串,则Python将不会在源模块导入时尝试编写.pyc文件。这相当于指定 -B选项。


如果file_name是一个包含函数定义的文件,是否会有性能提升? - Anton

7

从官方Python教程模块中:

为了加快模块的加载速度,Python会将每个模块的编译版本缓存到__pycache__目录下,文件名为module.version.pyc。其中,版本号包含编译文件的格式,通常包含Python版本号。例如,在CPython 3.6版本中,spam.py的编译版本会被缓存为__pycache__/spam.cpython-36.pyc

来自Python文档编程FAQs

当第一次导入模块时(或者当前编译文件创建后源文件已更改),应在.py文件所在目录的__pycache__子目录中创建一个包含编译代码的.pyc文件。.pyc文件的文件名以与.py文件相同的名称开头,并以.pyc结尾,中间部分取决于创建它的特定Python二进制文件。


6

在 Python 2.x 版本中,解释器编译代码时会生成.pyc文件。

而在 Python 3.x 版本中,解释器编译代码时会生成__pycache__文件。

alok@alok:~$ ls
module.py  module.pyc  __pycache__  test.py
alok@alok:~$

5
执行Python脚本会在内存中生成字节码,并保留直到程序关闭。如果导入一个模块以提高复用性,Python将创建一个缓存.pyc(PYC是“Python”“已编译”)文件,其中缓存了被导入模块的字节码。其目的是通过避免重新编译(只编译一次,多次运行策略)来加快Python模块的加载速度,当它们被重新导入时。文件名与模块名称相同。初始点后面的部分表示创建缓存的Python实现(可以是CPython),后跟其版本号。

5
Python解释器会编译*.py脚本文件,并将编译结果保存到__pycache__目录中。当再次执行该项目时,如果解释器发现*.py脚本未被修改,则跳过编译步骤,并运行之前生成的*.pyc文件,文件存储在__pycache__文件夹中。当项目较为复杂时,您可以缩短项目运行前的准备时间。如果程序很小,您可以通过使用带有B选项的python -B abc.py来忽略此选项。

4
在3.2及以上版本中,Python会将编译好的.pyc字节码文件保存在名为__pycache__的子目录中,该子目录位于源文件所在目录中,并且以标识创建它们的Python版本的文件名进行命名(例如script.cpython-33.pyc)。

我该如何避免创建“__pycache__”文件夹并且所有的.pyc文件应该与.py文件命名相同? - Ashwani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接