什么是 Python 中的 __pycache__ 文件夹?
off999 2024-10-12 06:17 58 浏览 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是否生成缓存文件夹,以及它们的存储位置。最后,虽然缓存的字节码可以使源代码不易被直接阅读,但它们并不等同于真正的代码混淆或加密,如果需要确保代码的安全性,最好使用专门的工具。
相关推荐
- 阿里云国际站ECS:阿里云ECS如何提高网站的访问速度?
-
TG:@yunlaoda360引言:速度即体验,速度即业务在当今数字化的世界中,网站的访问速度已成为决定用户体验、用户留存乃至业务转化率的关键因素。页面加载每延迟一秒,都可能导致用户流失和收入损失。对...
- 高流量大并发Linux TCP性能调优_linux 高并发网络编程
-
其实主要是手里面的跑openvpn服务器。因为并没有明文禁p2p(哎……想想那么多流量好像不跑点p2p也跑不完),所以造成有的时候如果有比较多人跑BT的话,会造成VPN速度急剧下降。本文所面对的情况为...
- 性能测试100集(12)性能指标资源使用率
-
在性能测试中,资源使用率是评估系统硬件效率的关键指标,主要包括以下四类:#性能测试##性能压测策略##软件测试#1.CPU使用率定义:CPU处理任务的时间占比,计算公式为1-空闲时间/总...
- Linux 服务器常见的性能调优_linux高性能服务端编程
-
一、Linux服务器性能调优第一步——先搞懂“看什么”很多人刚接触Linux性能调优时,总想着直接改配置,其实第一步该是“看清楚问题”。就像医生看病要先听诊,调优前得先知道服务器“哪里...
- Nginx性能优化实战:手把手教你提升10倍性能!
-
关注△mikechen△,十余年BAT架构经验倾囊相授!Nginx是大型架构而核心,下面我重点详解Nginx性能@mikechen文章来源:mikechen.cc1.worker_processe...
- 高并发场景下,Spring Cloud Gateway如何抗住百万QPS?
-
关注△mikechen△,十余年BAT架构经验倾囊相授!大家好,我是mikechen。高并发场景下网关作为流量的入口非常重要,下面我重点详解SpringCloudGateway如何抗住百万性能@m...
- Kubernetes 高并发处理实战(可落地案例 + 源码)
-
目标场景:对外提供HTTPAPI的微服务在短时间内收到大量请求(例如每秒数千至数万RPS),要求系统可弹性扩容、限流降级、缓存减压、稳定运行并能自动恢复。总体思路(多层防护):边缘层:云LB...
- 高并发场景下,Nginx如何扛住千万级请求?
-
Nginx是大型架构的必备中间件,下面我重点详解Nginx如何实现高并发@mikechen文章来源:mikechen.cc事件驱动模型Nginx采用事件驱动模型,这是Nginx高并发性能的基石。传统...
- Spring Boot+Vue全栈开发实战,中文版高清PDF资源
-
SpringBoot+Vue全栈开发实战,中文高清PDF资源,需要的可以私我:)SpringBoot致力于简化开发配置并为企业级开发提供一系列非业务性功能,而Vue则采用数据驱动视图的方式将程序...
- Docker-基础操作_docker基础实战教程二
-
一、镜像1、从仓库获取镜像搜索镜像:dockersearchimage_name搜索结果过滤:是否官方:dockersearch--filter="is-offical=true...
- 你有空吗?跟我一起搭个服务器好不好?
-
来人人都是产品经理【起点学院】,BAT实战派产品总监手把手系统带你学产品、学运营。昨天闲的没事的时候,随手翻了翻写过的文章,发现一个很严重的问题。就是大多数时间我都在滔滔不绝的讲理论,却很少有涉及动手...
- 部署你自己的 SaaS_saas如何部署
-
部署你自己的VPNOpenVPN——功能齐全的开源VPN解决方案。(DigitalOcean教程)dockovpn.io—无状态OpenVPNdockerized服务器,不需要持久存储。...
- Docker Compose_dockercompose安装
-
DockerCompose概述DockerCompose是一个用来定义和管理多容器应用的工具,通过一个docker-compose.yml文件,用YAML格式描述服务、网络、卷等内容,...
- 京东T7架构师推出的电子版SpringBoot,从构建小系统到架构大系统
-
前言:Java的各种开发框架发展了很多年,影响了一代又一代的程序员,现在无论是程序员,还是架构师,使用这些开发框架都面临着两方面的挑战。一方面是要快速开发出系统,这就要求使用的开发框架尽量简单,无论...
- Kubernetes (k8s) 入门学习指南_k8s kubeproxy
-
Kubernetes(k8s)入门学习指南一、什么是Kubernetes?为什么需要它?Kubernetes(k8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用程序。它...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
python入门到脱坑 输入与输出—str()函数
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
慕ke 前端工程师2024「完整」
-
失业程序员复习python笔记——条件与循环
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
