ChatGPT解决这个技术问题 Extra ChatGPT

什么是__pycache__?

据我了解,缓存是类似文件的加密文件。

我们如何处理 __pycache__ 文件夹?是我们提供给人们的东西而不是我们的源代码吗?它只是我的输入数据吗?这个文件夹不断被创建,它是做什么用的?

“是我们提供给人们的东西而不是我们的源代码吗?” - 不,你在一个很好的可安装包中给他们源代码,所以它很容易使用。
还没有人提到,但是您对缓存的定义很奇怪。缓存很简单的一个 component that stores data so future requests for that data can be served faster
Python 3.8 开始,您可以使用环境变量更改位置 来处理烦人的缓存目录:stackoverflow.com/a/57414308/1612318
缓存是保存内容副本的东西,以防您再次需要它,以免您不得不返回原始文件来获取它。它的设计目的是比去原来的地方更快。它可能会更快,因为它不必预处理或编译信息。或者它可能是更快的存储,例如 RAM 中的磁盘缓存或本地磁盘上的 Web 缓存。它本质上不是加密的(尽管有时可能是加密的),而且它并不总是“类似文件的文件”——它可以是一个文件、一堆文件、一块 RAM 等。

b
bad_coder

当您在 Python 中运行程序时,解释器首先将其编译为字节码(这过于简单化了)并将其存储在 __pycache__ 文件夹中。如果您在那里查看,您会发现一堆文件共享您项目文件夹中 .py 文件的名称,只有它们的扩展名是 .pyc.pyo。这些分别是程序文件的字节码编译版本和优化的字节码编译版本。

作为程序员,你基本上可以忽略它......它所做的只是让你的程序启动得更快一点。当您的脚本更改时,它们将被重新编译,如果您删除文件或整个文件夹并再次运行您的程序,它们将重新出现(除非您特别禁止该行为)。

当您将代码发送给其他人时,通常的做法是删除该文件夹,但您是否这样做并不重要。当您使用版本控制 (git) 时,此文件夹通常列在忽略文件 (.gitignore) 中,因此不包括在内。

如果您使用的是 CPython(这是最常见的,因为它是参考实现)并且您不想要该文件夹,那么您可以通过使用 -B 标志启动解释器来抑制它,例如

python -B foo.py

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


您还可以添加环境变量 PYTHONDONTWRITEBYTECODE=<any_value> 以永久禁止它。
澄清一下,这仅适用于 Python 3,对吗?
@JoeJ 是的,我认为这是真的。 python2 如果我没记错的话,将编译后的文件放在与原始文件相同的目录中。
一个重要的警告是,如果 .py 文件丢失,将使用缓存的 .pyc 文件而不是 .py 文件。在实践中,只有在删除(或重命名)模块时才会发生这种情况,所以这并不常见,但如果有些东西一直在“那里”,在挠头之后,运行 find 。 -name *.pyc |您的来源上的 xargs rm 可能是一个很好的第一反应。
find . -name '*.pyc' -delete 是的,find 有一个用于删除找到的文件的标志,因此您不必使用任何 xargs shananigans
f
fmalina

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

我不建议在开发过程中经常费力地删除这些文件或禁止创建,因为这会浪费您的时间。只需准备好递归命令(见下文)即可在需要时进行清理,因为字节码在极端情况下会变得陈旧(见注释)。

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

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

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

对于 Python 2,将 __pycache__ 替换为 *.pyc

这会在所有这些目录(.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 .

@DoTheEvo:它根本没有被创建,所以下次加载模块时没有加速。不会引发错误。
这不是一个好的答案。提问者想知道这些文件的用途。这个答案说“别担心”,然后让它们消失。
绝对打扰删除这些:这不是毫无意义的。在许多情况下,Python 很高兴不会检测到文件更改并运行缓存文件,从而使您陷入“为什么 f 仍然无法正常工作,我更改了代码,为什么在不存在的调用上仍然失败”的胡说八道。尤其是在测试框架中,pycache-by-default 是最差的。
什么情况?在过去的 10 年中,每次我怀疑字节码是问题所在,它实际上是在其他地方。
我不同意“不要打扰删除这些文件”的建议 - 已经多次看到此建议,最近一次是 Kenneth Reitz's "How To Python" (“字节码技巧”)
f
funnydman

使用以下行时会创建一个 __pycache__ 文件夹:

import file_name

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


F
FluxLemur

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

为了加快加载模块的速度,Python 将每个模块的编译版本缓存在名为 module.version.pyc 的 __pycache__ 目录中,其中版本编码了编译文件的格式;它通常包含 Python 版本号。例如,在 CPython 3.3 版中,spam.py 的编译版本将被缓存为 __pycache__/spam.cpython-33.pyc。这种命名约定允许来自不同版本和不同 Python 版本的编译模块共存。

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

也就是说,这个目录是由 Python 生成的,存在是为了让你的程序运行得更快。它不应该致力于源代码控制,而应该与您的本地源代码和平共处。

__pycache__ 是一个目录,其中包含由 python 自动生成的字节码缓存文件,即已编译的 python 或 .pyc 文件。您可能想知道为什么 Python 这种“解释型”语言有任何已编译的文件。 This SO question 解决了这个问题(绝对值得一读 this answer)。

python 文档更深入地了解它的工作原理以及它存在的原因:

它是在 python 3.2 中添加的,因为现有的在同一目录中维护 .pyc 文件的系统会导致各种问题,例如在使用不同版本的 Python 解释器运行程序时。有关完整功能规范,请参阅 PEP 3174。


E
Ehsan Barkhordar

导入模块时,

import file_name

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

它不会仅仅为了运行脚本而这样做,只有在导入文件时才会这样做。

(以前的版本用于将缓存的字节码存储为 .pyc 文件,这些文件在与 .py 文件相同的目录中乱扔垃圾,但从 Python 3 开始,它们被移至子目录以使事情更整洁。)

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


如果 file_name 是包含函数定义的文件,是否有任何性能提升?
Y
Yossarian42

来自官方 python 教程 Modules

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

来自 Python 文档 Programming FAQs

当一个模块第一次被导入时(或者当源文件在当前编译文件被创建之后发生了改变时)一个包含编译代码的 .pyc 文件应该在包含 .py 文件的目录的 __pycache__ 子目录中创建。 .pyc 文件的文件名以与 .py 文件相同的名称开头,以 .pyc 结尾,中间组件取决于创建它的特定 python 二进制文件。


A
Alok Tiwari

当解释器编译代码时,Python 版本 2.x 将具有 .pyc。

当解释器编译代码时,Python 版本 3.x 将具有 __pycache__。

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

M
Marcus Thornton

python 解释器编译 *.py 脚本文件并将编译结果保存到 __pycache__ 目录。

再次执行项目时,如果解释器识别出 *.py 脚本未被修改,则跳过编译步骤并运行之前生成的存储在 __pycache__ 文件夹中的 *.pyc 文件。

当项目复杂时,可以缩短项目运行前的准备时间。如果程序太小,您可以通过使用带有 B 选项的 python -B abc.py 来忽略它。


T
TechFree

执行 python 脚本会导致字节码在内存中生成并保存到程序关闭。如果导入了模块,为了更快的可重用性,Python 将创建一个缓存 .pyc(PYC 是 'Python' 'Compiled')文件,其中缓存了正在导入的模块的字节码。想法是通过避免在重新导入时重新编译(编译一次,运行多次策略)来加速 python 模块的加载。

文件名与模块名相同。初始点之后的部分表示创建缓存的 Python 实现(可能是 CPython),后跟其版本号。


n
notpeter

在 3.2 及更高版本中,Python 将 .pyc 编译后的字节码文件保存在名为 __pycache__ 的子目录中,该子目录位于源文件所在的目录中,文件名标识创建它们的 Python 版本(例如 script.cpython-33.pyc )


如何避免创建“pycache”文件夹并且所有 .pyc 应与 .py 文件命名相同?
V
Vipin Menon

下次启动应用程序时是否会自动调用 __pycache__ 中的字节码? IE:如果我们第一次运行某个应用程序 main.py,并且所有必要的模块都被编译并存储在 pycache 中,那么即使我调用 python main.py,下次它们也会自动使用吗?或者我们将不得不调用 python _pycache_/main.pyc


pycache 只是一个包含 .pyc 文件的目录,它只是用于缓存,以便在我们下次运行时加快执行速度,就像在使用 cookie 存储数据的浏览器中一样,所以下次我们打开同一页面时,它不必发出请求再次使用所有 css 文件,或者将其视为包含数据的数组,该数组使用类似的概念,即在 OS 中使用高速缓存存储数据。