百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

什么是 Python 中的 __pycache__ 文件夹?

off999 2024-10-12 06:17 51 浏览 0 评论

当您开发一个独立的 Python 脚本时,您可能不会注意到目录结构有什么异常。然而,当项目变得越来越复杂时,您通常会决定将部分功能提取到额外的模块或包中。这时,您可能会发现源文件旁边突然出现了一个 __pycache__ 文件夹,而且似乎是随机出现的:

project/
│
├── mathematics/
│   │
│   ├── __pycache__/
│   │
│   ├── arithmetic/
│   │   ├── __init__.py
│   │   ├── add.py
│   │   └── sub.py
│   │
│   ├── geometry/
│   │   │
│   │   ├── __pycache__/
│   │   │
│   │   ├── __init__.py
│   │   └── shapes.py
│   │
│   └── __init__.py
│
└── calculator.py

请注意,当多个子包相互嵌套时,__pycache__ 文件夹可能存在于项目目录树的不同层次。同时,包含 Python 源文件的其他包或文件夹可能不包含这个神秘的缓存目录。

注意:为了保持工作区的整洁,许多 Python IDE 和代码编辑器在开箱配置时都会隐藏 __pycache__ 文件夹,即使这些文件夹存在于您的文件系统中。

简而言之:它让导入 Python 模块变得更快

尽管 Python 是一种解释型编程语言,但它的解释器并不直接对 Python 代码进行操作,因为那样会非常慢。相反,当您运行一个 Python 脚本或导入一个 Python 模块时,解释器会将您的高级 Python 源代码编译成字节码,字节码是代码的中间二进制表示形式。

这种字节码能让解释器跳过重复的步骤,比如将代码编入抽象语法树并进行解析,以及在每次运行相同程序时验证其正确性。只要底层源代码没有改变,Python 就能重复使用中间表示,并立即准备执行。这样可以节省时间,加快脚本的启动速度。

请记住,虽然从 __pycache__ 加载编译过的字节码会使 Python 模块的导入速度更快,但这并不影响它们的执行速度!

为什么要使用字节码,而不是直接将代码编译成底层机器码?虽然机器码可以在硬件上执行,提供极致的性能,但它的可移植性和生成速度都不如字节码。

机器码是一组能被特定 CPU 架构理解的二进制指令,根据操作系统的不同,被封装成 EXE、ELF 或 Mach-O 等容器格式。相比之下,字节码提供了一个与平台无关的抽象层,编译速度通常更快。

Python 使用本地的 __pycache__ 文件夹来存储项目中导入模块的编译字节码。在随后的运行中,解释器将尝试从这些文件夹中加载模块的预编译版本,前提是它们与相应的源文件是最新的。请注意,只有在代码中导入模块而不是在终端中作为脚本执行时,才会触发这种缓存机制。

除了磁盘上的字节码缓存外,Python 还保留了一个内存中的模块缓存,您可以通过 sys.modules 字典访问它。它确保当您在程序的不同位置多次导入同一个模块时,Python 将使用已经导入的模块,而无需重新加载或重新编译。这两种机制共同作用,减少了导入 Python 模块的开销。
接下来,您将了解在导入模块时,Python 加载缓存字节码比编译源代码快多少。

从缓存加载模块的速度有多快?

缓存发生在幕后,通常不会被注意到,因为 Python 编译字节码的速度非常快。此外,除非您经常运行短时 Python 脚本,否则编译步骤与总执行时间相比仍然微不足道。尽管如此,如果没有缓存,如果您有很多模块并多次导入它们,那么与字节码编译相关的开销就会增加。

要测量缓存模块和未缓存模块的导入时间差,可以在 python 命令中传递 -X importtime 选项,或设置等效的 PYTHONPROFILEIMPORTTIME 环境变量。启用该选项后,Python 将显示一个表格,总结导入每个模块所需的时间,包括一个模块依赖于其他模块时的累计时间。

假设你有一个 calculator.py 脚本,它从本地 arithmetic.py 模块导入并调用了一个实用程序函数:

from arithmetic import add

add(3, 4)

导入的模块只定义了一个函数:

def add(a, b):
    return a + b

如您所见,主脚本将 3 和 4 这两个数字的加法运算委托给了从算术模块导入的 add() 函数。

注意:即使你使用from..import语法,它只是将指定的符号导入到当前的命名空间中,Python将读取并编译整个模块。此外未使用导入也会触发编译。

第一次运行脚本时,Python编译并保存你导入的模块的字节码到一个本地的__pycache__文件夹中。如果这样的文件夹不存在,那么Python会继续之前自动创建一个。现在当您再次执行脚本时,只要您没有更改相关的源代码,Python就应该能找到并加载缓存的字节码。

__pycache__文件夹里面有什么?


__pycache__文件夹中包含了模块的缓存版本,这些版本以.pyc文件的形式存储。.pyc文件是Python字节码的二进制表示形式,它们包含了模块的编译后的形式。



Python何时创建缓存文件夹?


Python在导入模块时会自动检查是否需要创建__pycache__文件夹。如果Python解释器有权限在当前目录下创建文件夹,且该目录下有Python源代码文件,则Python会自动生成__pycache__文件夹并在其中存储相应的缓存版本。


什么操作会使缓存失效?


缓存版本的生成是根据源代码文件的修改时间和内容进行的。如果源代码文件发生了更改,Python将重新生成缓存版本。因此,以下操作将使缓存失效:

  • 修改了源代码文件。
  • 从一个Python版本切换到另一个Python版本。
  • 在不同的操作系统上运行相同的代码。


删除缓存文件夹是否安全?


是的,删除__pycache__文件夹通常是安全的。Python会在需要时自动重新生成缓存版本。删除缓存文件夹可能会导致稍微延迟一点,因为Python需要重新编译源代码以生成新的缓存版本,但不会对代码的正确性产生任何影响。


如何递归删除所有缓存文件夹?


你可以使用操作系统提供的命令或Python的第三方库来递归删除所有的__pycache__文件夹。例如,在Unix/Linux系统上,你可以使用find命令:


find . -type d -name '__pycache__' -exec rm -r {} +

或者

import shutil
import os

def remove_pycache(folder):
    for root, dirs, files in os.walk(folder):
        for d in dirs:
            if d == '__pycache__':
                shutil.rmtree(os.path.join(root, d))

remove_pycache('.')

如何防止Python创建缓存文件夹?


如果你不希望Python创建__pycache__文件夹,你可以在运行Python脚本时设置环境变量PYTHONDONTWRITEBYTECODE为1。


export PYTHONDONTWRITEBYTECODE=1

或者

import sys
sys.dont_write_bytecode = True

如何将缓存存储在集中的文件夹中?


如果你希望将所有缓存文件存储在一个集中的文件夹中,而不是在每个模块所在的目录中创建__pycache__文件夹,你可以设置环境变量PYTHONDONTWRITEBYTECODE为一个特定的目录路径。


export PYTHONDONTWRITEBYTECODE=/path/to/cache/folder


缓存的.pyc文件里面是什么?


缓存的.pyc文件包含了模块的编译后的字节码。这些字节码是由Python编译器生成的,可以直接由Python虚拟机执行。

如何读取和执行缓存的字节码?


你可以使用Python的importlib模块来读取和执行缓存的字节码。以下是一个简单的示例:


import importlib.util

# Load cached bytecode
spec = importlib.util.spec_from_file_location("module_name", "/path/to/module.pyc")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

# Use the module
module.some_function()


字节码能够混淆Python程序吗?


虽然缓存的字节码不是为了隐藏代码而设计的,但它们确实可以使源代码不易被直接阅读。然而,这并不等同于真正的代码混淆或加密。如果你需要确保代码的安全性,最好使用专门的代码混淆工具。


如何反汇编缓存的字节码?

你可以使用Python标准库中的dis模块来反汇编缓存的字节码。以下是一个示例:

import dis

# Disassemble cached bytecode
with open("/path/to/module.pyc", "rb") as f:
    dis.dis(f.read())

结论

__pycache__文件夹是Python中用于存储模块缓存版本的特殊文件夹。它可以提高模块导入的速度,并且在大型项目中尤其有用。虽然删除缓存文件夹通常是安全的,但你也可以通过设置环境变量来控制Python是否生成缓存文件夹,以及它们的存储位置。最后,虽然缓存的字节码可以使源代码不易被直接阅读,但它们并不等同于真正的代码混淆或加密,如果需要确保代码的安全性,最好使用专门的工具。

相关推荐

实战:用 Python+Flask+Echarts 构建电商实时数据大屏

在电商运营中,实时掌握销售趋势、用户行为等核心数据是决策的关键。本文将从实战角度,详解如何用Python+Flask+Echarts技术栈,快速搭建一个支持实时更新、多维度可视化的电商数据大屏,帮...

DeepSeek完全使用手册:从新手到高手的2000字实操指南

一、工具定位与核心功能矩阵(200字)DeepSeek是一款专注于深度推理的强大AI助手,其功能丰富多样,可归纳为4大能力象限:plaintext差异化优势:DeepSeek支持最长达16Ktok...

Python绘制可爱的图表 cutecharts

一个很酷的python手绘样式可视化包——可爱的图表cutecharts。Cutecharts非常适合为图表提供更个性化的触感。Cutecharts与常规的Matplotlib和Seabo...

第十二章:Python与数据处理和可视化

12.1使用pandas进行数据处理12.1.1理论知识pandas是Python中最常用的数据处理库之一,它提供了高效的数据结构和数据分析工具。pandas的核心数据结构是Serie...

5分钟就能做一个Excel动态图表,你确定不学学?(纯gif教学)

本文说明下图是一个比较酷炫的Excel动态图表,最难的部分就是用到了一个复选框控件。其实这个控件我很早就见过,但是不会用呀!望洋兴叹。这次呢,我也是借着这个文章为大家讲述一下这个控件的使用。本文没有...

Python数据可视化:从Pandas基础到Seaborn高级应用

数据可视化是数据分析中不可或缺的一环,它能帮助我们直观理解数据模式和趋势。本文将全面介绍Python中最常用的三种可视化方法。Pandas内置绘图功能Pandas基于Matplotlib提供了简洁的绘...

如何使用 Python 将图表写入 Excel

将Python生成的图表写入Excel文件是数据分析和可视化中常见的需求。Python提供了多种库(如matplotlib、openpyxl和xlsxwriter)来实现这一功能。本文...

Excel 图表制作太痛苦?用 Python 生成动态交互图表

做个动态图表花了3小时?你该换方法了!上周帮销售部做季度汇报图表,Excel操作把我整崩溃了——插入折线图后发现数据源选错,重新选择又得调格式想做动态筛选图表,捣鼓"开发工具"...

Python Matplotlib 入门教程:可视化数据的基石

一、简介Matplotlib是Python中最流行的数据可视化库,提供从简单折线图到复杂3D图形的完整解决方案。其核心优势在于:o灵活性强:支持像素级样式控制o兼容性好:与NumPy、Pa...

20种Python数据可视化绘图 直接复制可用

本文介绍20种python数据绘图方法,可直接用于科研绘图或汇报用图。1.折线图(LinePlot)-描述数据随时间或其他变量的变化。importmatplotlib.pyplotasp...

Python os模块完全指南:轻松玩转文件管理与系统操作

Pythonos模块完全指南:轻松玩转文件管理与系统操作os模块是Python与操作系统对话的"瑞士军刀",学会它能让你轻松管理文件、操控路径、获取系统信息。本教程通过场景化案例+...

Python中h5py与netCDF4模块在Anaconda环境的下载与安装

本文介绍基于Anaconda环境,下载并安装Python中h5py与netCDF4这两个模块的方法。h5py与netCDF4这两个模块是与遥感图像处理、地学分析等GIS操作息息相关的模块,应用...

python中的模块、库、包有什么区别?

一文带你分清Python模块、包和库。一、模块Python模块(Module),是一个Python文件,以.py结尾,包含了Python对象定义和Python语句。模块能定义函数,类和变...

centos7 下面使用源码编译的方式安装python3.11

centos7下面使用源码编译的方式安装python3.11,步骤如下:cd/root#只是将python3.11的安装包下载到/root目录下wgethttps://www.python.o...

Python其实很简单 第十四章 模块

模块是一组程序代码,可以是别人已经写好的,也可以是自己编写的,但都是已经存在的,在编程时直接使用就可以了。模块机制的最大好处就是程序员不再编写重复的代码,而直接利用已有的成果,这样就能将更多的精力投入...

取消回复欢迎 发表评论: