VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > 简明python教程 >
  • 如何让ython运行地超快的10个方法,新手必学

大部门人使用 python 是因为它非常方便,而不是因为它速度快。过多的第三方库使得 python 相比于 Java 和 C 的性能差距较大。但也是可以理解的,因为在大部分情况下,开发速度优先于执行速度。另外

但也不要过于担心 python 的速度,这并不一定是一个非此即彼的命题。经过适当优化,Python 应用程序可以以惊人的速度运行 —— 也许还不能达到 Java 或 C 语言的速度,但是对于 Web 应用程序、数据分析、管理和自动化工具以及大多数其他用途来说,速度已经足够快了。快到你可能会忘记了你是在用应用程序性能换取开发人员的生产力。

优化 Python 性能不能单从一个角度上看。而是应用所有可用的优化方法,并选择最适合当前场景的多种方法的集合。(Dropbox 的员工有一个最令人瞠目的例子,展示了 python 优化的强大功能,点击链接查看。)

在本文中,我将简单讲述许多常见的 python 优化方法。有些是临时措施,只需要简单地将一项转换为另一项 (例如更换 Python 解释器),但是那些带来最大收益的方法将需要更详细的工作。

 

1. 算速度、算速度、算速度!

如果你不能够找出速度慢的原因所在,你就不能确定你的 python 应用程序为什么运行地不够理想。

计算的方法有很多,你可以尝试 python 内置的 cProfile 模块 进行简单的计算分析,如果需要更高的精度(计算每行语句运行时间),可以使用 line_profiler 第三方工具。通常而言,从计算程序的函数运行时间进行分析就能够给你提供改进方案,所以推荐使用 profilehooks 第三方库,它能计算单个函数的运行时间。

你可能需要更多的挖掘才能发现为什么你的程序某个地方这么慢、怎么修复它。重点在于缩小你的排查范围,逐渐细化到某条语句上。

 

2. 缓存需要重复使用的数据

当你可以把需要计算出来的数据保存下来的时候,千万不要重复上千次去计算它。如果你有一个经常需要使用的函数,而且返回的是可预测的结果,Python 已经给你提供了一个选项,能将其缓存到内存中。后续的函数调用如果是一样的,将立即返回结果。

有许多方法都可以做到,比如说:使用 python 的一个本地库:functools,拥有一个装饰器,叫 @functools.lru_cache,它能够缓存函数最近的 N 个调用,当缓存的值在特定时间内保持不变的时候这个非常好用,比如说列出最近一天使用的物品。

 

3. 将数学计算重构为 NumPy

如果你的 Python 程序中有基于矩阵或数组的数学运算,并且希望更高效地对它们进行计算,那么你就应该使用 NumPy,因为它通过使用 C 库来完成繁重的工作,比原生 python 解释器能更快得处理数组,而且能比 Python 内置数据结构更有效地存储数字数据。

NumPy 还可以极大地加速相对普通的数学运算。该包为许多常见的 Python 数学操作 (如 min 和 max) 提供了替换,这些操作的速度比原始 Python 快很多倍。

NumPy 的另一个优点是对大型对象 (比如包含数百万项的列表) 能更有效地使用内存。一般来说,如果用传统的 Python 表示类似于 NumPy 中的大型对象,那么它们将占用大约四分之一的内存。

重写 Python 算法以使用 NumPy 需要做一些工作,因为需要使用 NumPy 的语法重新声明数组对象。但是 NumPy 在实际的数学操作中使用 Python 现有的习惯用法 (+、- 等等),所以切换到 NumPy 并不会让人太迷惑。

 

4. 使用 C 库

NumPy 使用 C 编写的库是一种很好的方法。如果现有的 C 库能够满足你的需求,那么 Python 及其生态系统将提供几个选项来连接到该库并利用其提高速度。

最常用的方法是 Python 的 ctypes 库](https://pythondict.com/tag/%e5%ba%93/ “库”)。因为 ctypes 与其他 Python 应用程序广泛兼容,所以它是最好的起点,但也并不是唯一的,CFFI 项目为 C. Cython 提供了一个更优雅的接口 (参见下面第五点),也可以用来包装外部库,代价是你必须学习 Cython 的标记方法。

 

5. 转换为 Cython

如果你非常追求速度,应该用 C 而不是 python,但是对于我这种有 python 依赖症的人来说,对 C 天生就有种畏惧。现在有一个很好的解决办法出来了。

Cython 允许 Python 用户方便地访问 C 的速度。现有的 Python 代码可以逐步转换为 C :首先通过 Cython 将所述代码编译为 C,然后通过添加类型注释以获得更快的速度。

不过,Cython 不能变魔术。按原样转换为 Cython 的代码通常运行速度通常不会加快超过 15%到 50%,因为该级别的大多数优化都集中在减少 Python 解释器的开销上。只有在为 Cython 模块提供类型注释时才允许将相关代码转换为纯 C,这时候的速度提升才最大。

 

6. 使用多线程

由于全局解释器锁(GIL)的存在,Python 规定一次只执行一个线程,以避免在使用多个线程时出现状态问题。它的存在有充分的理由,但依然很讨厌。

随着时间的推移,GIL 的效率显著提高 (这是为什么你应该用 python3 的其中一个原因),但是核心问题仍然存在。为了解决这个问题,Python 提供了多处理模块(multiprocessing)来在单独的内核上运行 Python 解释器的多个进程。状态可以通过共享内存或服务器进程共享,数据可以通过队列或管道在进程实例之间传递。

您仍然必须手动管理进程之间的状态。此外,启动多个 Python 实例并在它们之间传递对象也会涉及不少开销。尽管如此,多处理库还是很有用的。另外,使用了 C 库的 Python 模块和包 (如 NumPy) 也是完全避免 GIL 的。这也是推荐它们提高速度的另一个原因。

 

7. 知道你的库正在干嘛

简单地输入 import xyz 是多么方便啊,但是你知道,第三方库虽然可以改变应用程序的性能,但并不总是向好的方向发展。

有时,你加了某个模块的时候,应用程序反而变慢了,这就是来自特定库的模块构成瓶颈。同样,仔细计算运行时间也会有所帮助,有时则不那么明显。示例:Pyglet 是一个用于创建窗口图形化应用程序的库,它自动启用调试模式,这将极大地影响性能,直到显式禁用为止。除非阅读文档,否则你可能永远不会意识到这一点。多读书,多了解情况。

 

8. 意识到平台间的速度差异

Python 的运行是跨平台的,但这并不意味着每个操作系统 (Windows、Linux、OS X) 的特性都可以在 Python 下抽象出来。大多数情况下,你需要了解平台的细节,比如路径命名约定等等。

但在性能方面,理解平台的差异也很重要。例如,有些 python 脚本需要使用 Windows 的 api 去访问一些特定的应用,这些应用也可能会减慢运行速度。

 

9. 使用 pypy 运行程序

CPython 是 Python 最常用的优化方案,因为它优先考虑兼容性而不是原始速度。对于那些想把速度放在首位的程序员来说,PyPy 是一个 Python 更好的方案,它配备了一个 JIT 编译器来加速代码的执行(编译为 C 代码)。

因为 PyPy 被设计为 CPython 的一个临时替代品,所以它是获得快速性能提升的最简单方法之一。大多数 Python 应用程序将完全按原样运行在 PyPy 上。然而,充分利用 PyPy 可能需要不断地测试。你将会发现,长时间运行的应用程序更有可能从 PyPy 中获得了最大的性能收益,因为编译器会随着时间分析执行情况。对于运行和退出的简短脚本,最好使用 CPython,因为性能的提高不足以克服 JIT 的开销。

 

10. 升级到 python3

如果你用的是 python2。而且没有压倒一切的理由 (比如一个不兼容的模块) 坚持使用它,你应该跳到 python3。

Python 3 中还有许多 Python 2.x 中没有的构造和优化。例如,Python 3.5 使异步变得不那么棘手,async 和 await 关键字成为语言语法的一部分。Python 3.2 对全局解释器锁进行了重大升级,显著改进了 Python 处理多线程的方式。



相关教程