加速 Python 程序的 10 个技巧
gudong366 2025-03-19 14:15 11 浏览
有很多方法可以提高 Python 应用程序的性能。以下是加快 Python 速度的 10 个硬核编码技巧。
总的来说,人们使用 Python 是因为它方便且对程序员友好,而不是因为它快速。大量的第三方库和对 Python 的广泛行业支持在很大程度上弥补了它不具备 Java 或 C 的原始性能。开发速度优先于执行速度。
但在许多情况下,它不一定是一个非此即彼的命题。经过适当优化后,Python 应用程序可以以惊人的速度运行,虽然速度可能不如 Java 或 C 语言快,但对于 Web 应用程序、数据分析、管理和自动化工具以及大多数其他用途来说已经足够快了。通过正确的优化,您甚至可能不会注意到应用程序性能和开发人员工作效率之间的权衡。
优化 Python 性能并不归结为任何一个因素。相反,它是关于应用所有可用的最佳实践并选择最适合手头场景的最佳实践。(Dropbox 的人们有一个最令人瞠目结舌的例子,展示了 Python 优化的力量。
在本文中,我将讨论 10 种常见的 Python 优化。有些是临时措施,只需要将一个项目换成另一个项目(例如更改 Python 解释器);其他 API 的回报更高,但也需要更详细的工作。
让 Python 程序运行得更快的 10 种方法
- 测量、测量、测量
- 重复使用的数据
- 将 math 移动到 NumPy
- 将 math 移动到 Numba
- 使用 C 库
- 转换为 Cython
- 并行使用 multiprocessing
- 了解您的库在做什么
- 了解您的平台在做什么
- 使用 PyPy 运行
测量、测量、测量
正如那句老话所说,你不能错过你不衡量的东西。同样,如果不找出缓慢的原因,就无法找出任何给定 Python 应用程序运行不佳的原因。
通过 Python 的内置 cProfile 模块从简单的分析开始,如果您需要更高的精度或更深入的洞察,请转向更强大的分析器。通常,通过对应用程序进行基本功能级检查所收集的见解提供了足够的视角。(您可以通过 profilehooks模块提取单个函数的配置文件数据。
为什么应用程序的特定部分如此缓慢以及如何修复它,可能需要更多的挖掘。关键是缩小关注范围,使用硬数字建立基线,并尽可能在各种使用和部署场景中进行测试。不要过早优化。猜测让你无处可去。
来自 Dropbox 的示例(上面链接)显示了分析的有用性。“正是测量告诉我们 HTML 转义一开始很慢,”开发人员写道,“如果不测量性能,我们永远不会猜到字符串插值会如此缓慢。
重复使用的数据
当您可以执行一次并保存结果时,永远不要执行一千次工作。如果您有一个经常调用的函数,该函数返回可预测的结果,Python 会为您提供将结果缓存到内存中的选项。返回相同结果的后续调用几乎会立即返回。
各种示例说明了如何执行此操作;我最喜欢的记忆几乎是尽可能少的。但是 Python 内置了此功能。Python 的原生库之一 functools 具有 @functools.lru_cache装饰器,它缓存对函数的 n 次最新调用。当您缓存的值发生变化但在特定时间窗口内相对静态时,这很方便。一天中最近使用的项目列表就是一个很好的例子。
请注意,如果您确定对函数的调用种类将保持在合理的范围内(例如,100 个不同的缓存结果),则可以使用性能更高的 @functools.cache。
将 math 移动到 NumPy
如果您正在进行基于矩阵或基于数组的数学运算,并且不希望 Python 解释器妨碍您,请使用 NumPy。通过利用 C 库来完成繁重的工作,NumPy 提供了比原生 Python 更快的数组处理。它还比 Python 的内置数据结构更有效地存储数值数据。
NumPy 的另一个好处是可以更有效地将内存用于大型对象,例如包含数百万个项目的列表。平均而言,像 NumPy 中的大型对象占用的内存大约是用传统 Python 表示时所需内存的四分之一。请注意,从作业的正确数据结构开始会有所帮助,这本身就是一种优化。
重写 Python 算法以使用 NumPy 需要一些工作,因为数组对象需要使用 NumPy 的语法声明。此外,最大的加速来自使用 NumPy 特定的 “广播” 技术,其中函数或行为应用于数组。花点时间深入研究 NumPy 的文档,了解有哪些功能可用以及如何很好地使用它们。
此外,虽然 NumPy 适合加速基于矩阵或数组的数学运算,但它并不能为在 NumPy 数组或矩阵之外执行的数学运算提供有用的加速。涉及传统 Python 对象的数学不会加速。
将 math 移动到 Numba
另一个用于加速数学运算的强大库是 Numba。编写一些用于数值操作的 Python 代码,并使用 Numba 的 JIT(即时)编译器包装它,生成的代码将以机器原生的速度运行。Numba 不仅提供 GPU 驱动的加速(CUDA 和 ROC),而且还具有特殊的“nopython”模式,该模式试图通过尽可能不依赖 Python 解释器来最大限度地提高性能。
Numba 还与 NumPy 携手合作,因此您可以两全其美 — NumPy 可以解决所有操作,而 Numba 可以解决所有其他操作。
使用 C 库
NumPy 使用用 C 编写的库是一个很好的模拟策略。如果现有的 C 库可以满足您的需要,Python 及其生态系统提供了多种选项来连接到该库并利用其速度。
最常见的方法是 Python 的 ctypes 库。由于 ctypes 与其他 Python 应用程序(和运行时)广泛兼容,因此它是最好的起点,但它远非唯一的游戏。CFFI 项目为 C. Cython(见下文)提供了更优雅的接口,也可用于编写您自己的 C 库或包装外部、现有库,但代价是必须学习 Cython 的标记。
这里有一个警告:通过最大限度地减少跨越 C 和 Python 之间边界的往返次数,您将获得最佳结果。每次在它们之间传递数据时,都会对性能造成影响。如果可以选择在紧密循环中调用 C 库,也可以选择将整个数据结构传递给 C 库并在其中执行循环内处理,请选择第二个选项。您将减少域之间的往返次数。
转换为 Cython
如果您想要速度,请使用 C 语言,而不是 Python。但对于 Pythonistas 来说,编写 C 代码会带来许多干扰 — 学习 C 的语法、整理 C 工具链(现在我的头文件怎么了?)等等。
Cython 允许 Python 用户方便地访问 C 的速度。现有的 Python 代码可以增量转换为 C 语言 — 首先使用 Cython 将所述代码编译为 C,然后添加类型注释以提高速度。
Cython 不是一根神奇的魔杖。将代码按原样转换为 Cython,如果没有类型公告,则运行速度通常不会超过 15% 到 50%。这是因为该级别的大多数优化都侧重于减少 Python 解释器的开销。当您的变量可以注释为 C 类型时,最大的收益来自于此,例如,机器级 64 位整数,而不是 Python 的 int 类型。由此产生的加速可以提高几个数量级。
CPU 密集型代码从 Cython 中受益最大。如果你已经分析了(你已经分析了,不是吗?)并发现代码的某些部分使用了绝大多数 CPU 时间,那么这些是 Cython 转换的极好候选者。受 I/O 限制的代码(如长时间运行的网络操作)从 Cython 获得的好处很小或根本没有。
与使用 C 库一样,另一个重要的性能增强技巧是将到 Cython 的往返次数保持在最低限度。不要编写重复调用“Cythonized”函数的循环;在 Cython 中实现循环并一次性传递数据。
并行使用 multiprocessing
传统的 Python 应用程序(在 CPython 中实现的应用程序)一次只执行一个线程,以避免在使用多个线程时出现的状态问题。这就是臭名昭著的全局解释器锁 (GIL)。它的存在有充分的理由,但这并没有使它变得不那么糟糕。
CPython 应用程序可以是多线程的,但由于 GIL 的原因,CPython 并不真正允许这些线程在多个内核上并行运行。随着时间的推移,GIL 的效率大大提高,并且正在努力完全消除它,但目前核心问题仍然存在。
一种常见的解决方法是 multiprocessing 模块,该模块在单独的内核上运行 Python 解释器的多个实例。状态可以通过共享内存或服务器进程共享,并且数据可以通过队列或管道在进程实例之间传递。
您仍然必须在进程之间手动管理状态。此外,启动多个 Python 实例并在它们之间传递对象涉及的开销不小。但对于受益于跨内核并行性的长时间运行的进程,multiprocessing 库很有用。
顺便说一句,使用 C 库(例如 NumPy 或 Cython)的 Python 模块和包能够完全避免 GIL。这是推荐它们以提升速度的另一个原因。
了解您的库在做什么
只需键入 include foobar 并利用无数其他程序员的工作是多么方便啊!但您需要注意,第三方库可能会改变应用程序的性能,但并不总是变得更好。
有时,这以明显的方式表现出来,例如当来自特定库的模块构成瓶颈时。(同样,分析会有所帮助。有时它不那么明显。例如,考虑 Pyglet,这是一个用于创建窗口图形应用程序的便捷库。Pyglet 会自动启用调试模式,这会极大地影响性能,直到它被显式禁用。除非您阅读库的文档,否则您可能永远不会意识到这一点,因此当您开始使用新库时,请仔细阅读并了解情况。
了解您的平台在做什么
Python 可以跨平台运行,但这并不意味着每个操作系统(Windows、Linux、macOS)的特性在 Python 下完全抽象出来。大多数时候,了解平台细节(如路径命名约定)是值得的,其中有帮助程序函数。例如,pathlib 模块抽象出特定于平台的 path 约定。控制台处理在 Windows 和其他操作系统之间也有很大差异;因此,像 rich 这样的抽象库很受欢迎。
在某些平台上,某些功能根本不受支持,这可能会影响您编写 Python 的方式。例如,Windows 没有进程分叉的概念,因此一些多处理功能在那里的工作方式不同。
最后,Python 本身在平台上的安装和运行方式也很重要。例如,在 Linux 上, pip 通常与 Python 本身分开安装;在 Windows 上,它会随 Python 自动安装。
使用 PyPy 运行
CPython 是最常用的 Python 实现,它优先考虑兼容性而不是原始速度。对于希望将速度放在首位的程序员,可以使用 PyPy,这是一种配备 JIT 编译器的 Python 实现,可加速代码执行。
由于 PyPy 被设计为 CPython 的直接替代品,因此它是快速提高性能的最简单方法之一。许多常见的 Python 应用程序将完全按原样在 PyPy 上运行。通常,应用程序对 “vanilla” Python 的依赖程度越高,它就越有可能在不修改的情况下在 PyPy 上运行。
但是,充分利用 PyPy 可能需要测试和研究。您会发现,长时间运行的应用程序从 PyPy 中获得的性能提升最大,因为编译器会分析一段时间内的执行情况,以确定如何加快速度。对于仅运行和退出的短脚本,最好使用 CPython,因为性能提升不足以克服 JIT 的开销。
请注意,PyPy 对 Python 的支持往往滞后于该语言的最新版本。当 Python 3.12 是最新的时,PyPy 仅支持最高版本 3.10。此外,使用 ctypes 的 Python 应用程序可能并不总是按预期运行。如果您正在编写可能同时在 PyPy 和 CPython 上运行的内容,则单独处理每个解释器的用例可能是有意义的。
相关推荐
- U盘文件被删怎么简单恢复(u盘里的文件被误删了怎么找回)
-
现在这个社会不是靠关系靠路子,主要还是靠实力。刘强在机关工作,人长得帅气,工作能力又强。唯独一样不好,脾气太大,动不动就发火,因为小事常和同事发生口角。一次他火大的差点把办公桌给掀翻了,领导见他野蛮的...
- 不小心删除了一些文件?9 个最佳免费硬盘恢复软件
-
恢复您曾经无意或意外删除的所有文件和数据。您是否曾经错误地删除了一个对您的工作至关重要并导致您丢失所有进度的文件?我们为您提供了一些最好的免费硬盘恢复软件,以帮助您恢复意外删除的文件,以解决您的文件删...
- Studio 中文版:数据救援神器,误删 / 分区损坏 / RAID 恢复一键找回
-
Studio中文版:数据救援神器,误删/分区损坏/RAID恢复一键找回当文件意外删除、分区损坏,或RAID阵列崩溃时,一款可靠的数据恢复工具往往能挽回关键损失。R-Studio中文版...
- 你值得拥有的11款Linux数据恢复工具
-
如果你使用的是Linux操作系统,那么你一定想知道一旦硬盘崩溃的话又该如何保存和恢复数据。其实,现在有很多Linux数据恢复工具可以让我们摆脱数据安全的困扰。小编已经为各位准备好了一些最好的Linux...
- 误删文件内容怎么恢复(误删文件内容怎么恢复回来)
-
在日常使用电脑的过程中,误删文件的情况时有发生。无论是由于操作失误还是病毒攻击,误删文件都会给我们带来不小的困扰。幸运的是,随着技术的发展,误删文件恢复已不再是难题。本文将介绍几款国内外知名的误删...
- u盘如何恢复删除的文件?推荐5款u盘数据恢复软件!
-
在日常生活与工作中,U盘作为便捷的数据存储载体,频繁用于传输和保存各类重要文件。然而,误删文件的情况却时有发生,无论是珍贵的照片、重要的工作文档,还是精心制作的视频,一旦删除,都可能带来不小的麻烦。...
- 怎么恢复删除的数据?5种有效的数据恢复方法汇总!
-
在数字化办公与生活的时代,电脑里的每一份数据都承载着重要信息。然而,一个误操作就可能导致数据被删除,无论是尚未保存的重要文档,还是珍藏多年的照片,都可能瞬间“消失”。但其实,数据删除并不意味着永久丢...
- u盘删除文件怎么找回?5个数据恢复工具汇总,助你巧妙恢复数据!
-
在日常使用U盘的过程中,误删文件的情况时有发生,重要的工作文档、珍贵的照片视频一旦消失,难免让人焦急万分。别担心,只要选对数据恢复工具,被删除的数据仍有找回的可能。下面就为你汇总5款实用的数据...
- Linux下恢复误删文件:思路+实践(linux删除如何恢复)
-
周五篮球群里有人问误删文件了怎么恢复,得知是ext4文件系统之后我推荐了ext4magic这个工具,然后又有人提到了xfs的话怎么办,正好前几天看到DaveChinner在邮件列表里提到了这个问题,...
- 苹果放大招!不用虚拟机了,Mac直接跑Linux容器,开发者效率翻倍
-
苹果这次真给开发者送福利了!今天凌晨(6月10日),苹果在官宣的Containerization框架直接炸了技术圈——Mac现在能原生运行Linux容器镜像了!这可不是虚拟机那种“套娃”方案,而是基...
- 7 款老牌经典软件,值得收藏(经典老歌软件)
-
Calibrehttps://calibre-ebook.com/Calibre是一个电脑电子书管理软件。肯定有人说了,电子书还要管理?那当然了。它的功能更强大的让你想象不到,首先它可以导入PDF,...
- 神仙级的免费开源电子书阅读器,还支持听书功能
-
神仙级的免费开源电子书阅读器,还支持听书功能,极空间部署『KoodoReader』哈喽小伙伴们好,我是Stark-C~前段时间不是给大家分享的电子书管理工具『TaleBook』嘛~,然后就有粉丝私信...
- 如何在Ubuntu系统中重置root密码(ubuntu忘记密码重置root密码命令)
-
很多人有个问题,就是喜欢把密码设置得很长很复杂,结果谁也没防住,却成功防住了自己ヽ(.ˇдˇ;)ノ对于现代人,特别是年轻人,都有过忘记密码的经历吧。在这篇文章中,我们来了解如何在Ubuntu1...
- 5款功能强大的PDF阅读器,让PDF阅读更轻松
-
分享5款功能强大的PDF阅读器,拥有丰富的PDF阅读工具,支持PDF文档划线、笔记、标记等操作,让PDF阅读更轻松!1.嗨动PDF编辑器一款实用的PDF处理软件,不仅可以阅读PDF文档,还能直接编辑、...
- 上班摸鱼利器! 免费好用的电子书阅读器,NAS轻松部署Koodo Reader
-
哈喽,大家好我是生活爱好者。笔者也是一名小说爱好者,平时用手机用某信读书,会员也开了,在家看体验也不错,但是上班的时候,在工作快速完成之后,想摸个鱼用手机就不太方便啦,作为爱折腾的人,必须要工作认真,...
- 一周热门
- 最近发表
- 标签列表
-
- linux一键安装 (31)
- linux运行java (33)
- ln linux (27)
- linux 磁盘管理 (31)
- linux 内核升级 (30)
- linux 运行python (28)
- linux 备份文件 (30)
- linux 网络测试 (30)
- linux 网关配置 (31)
- linux jre (32)
- linux 杀毒软件 (32)
- linux语法 (33)
- linux博客 (33)
- linux 压缩目录 (37)
- linux 查看任务 (32)
- 制作linux启动u盘 (35)
- linux 查看存储 (29)
- linux乌班图 (31)
- linux挂载镜像 (31)
- linux 软件源 (28)
- linux题目 (30)
- linux 定时脚本 (30)
- linux 网站搭建 (28)
- linux 远程控制 (34)
- linux bind (31)