提高python代码运行效率的一些建议


Posted in Python onSeptember 29, 2020

1. 优化代码和算法

一定要先好好看看你的代码和算法。许多速度问题可以通过实现更好的算法或添加缓存来解决。本文所述都是关于这一主题的,但要遵循的一些一般指导方针是:

  • 测量,不要猜测。 测量代码中哪些部分运行时间最长,先把重点放在那些部分上。
  • 实现缓存。 如果你从磁盘、网络和数据库执行多次重复的查找,这可能是一个很大的优化之处。
  • 重用对象,而不是在每次迭代中创建一个新对象。Python 必须清理你创建的每个对象才能释放内存,这就是所谓的“垃圾回收”。许多未使用对象的垃圾回收会大大降低软件速度。
  • 尽可能减少代码中的迭代次数,特别是减少迭代中的操作次数。
  • 避免(深度)递归。 对于 Python 解释器来说,它需要大量的内存和维护(Housekeeping)。改用生成器和迭代之类的工具。
  • 减少内存使用。 一般来说,尽量减少内存的使用。例如,对一个巨大的文件进行逐行解析,而不是先将其加载到内存中。
  • 不要这样做。 听起来很傻是吧?但是你真的需要执行这个操作吗?不能晚点儿再执行吗?或者可以只执行一次,并且它的结果可以存储起来,而不是一遍又一遍地反复计算?

2. 使用 PyPy

你可能正在使用 Python 的参考实现 CPython。之所以称为 CPython,是因为它是用 C 语言编写的。如果你确定你的代码是 CPU 密集型(CPU bound)(如果你不知道这一术语,请参见本文“使用线程”一节)的话,那么你应该研究一下 PyPy,它是 CPython 的替代方案。这可能是一种快速解决方案,无需更改任何一行代码。

PyPy 声称,它的平均速度比 CPython 要快 4.4 倍。它是通过使用一种称为 Just-in-time(JIT,即时编译)技术来实现的。Java 和 .NET 框架就是 JIT 编译的其他著名的例子。相比之下,CPython 使用解释来执行代码。虽然这一做法提供了很大的灵活性,但速度也变得慢了下来。

使用 JIT,你的代码是在运行程序时即时编译的。它结合了 Ahead-of-time(AOT,提前编译)技术的速度优势(由 C 和 C++ 等语言使用)和解释的灵活性。另一个优点是 JIT 编译器可以在运行时不断优化代码。代码运行的时间越长,它就会变得越优化。

PyPy 在过去几年中取得了长足的进步,通常情况下,它可以作为 Python 2 和 Python 3 的简易替换方案。使用 Pipenv 这样的工具,它也可以完美地工作,试试看吧!

3. 使用线程

大部分软件都是 IO 密集型,而不是 CPU 密集型。如果你对这些术语还不熟悉的话,请看看下面的解释:

  • IO 密集型(I/O bound):软件主要是等待输入 / 输出操作完成才能工作。在从网络或缓慢的存储中获取数据时,通常会出现这种情况。
  • CPU 密集型(CPU bound):软件占用了大量的 CPU 资源。它使用了 CPU 所有的能力来产生所需的结果。

在等待来自网络或磁盘的应答时,你可以使用多个线程使其他部分保持运行状态。

一个线程是一个独立的执行序列。默认情况下,Python 程序有一个主线程。但你可以创建更多的主线程,并让 Python 在它们之间切换。这种切换发生得如此之快,以至于它们看上去就好像是在同时并排运行一样。

提高python代码运行效率的一些建议

但与其他编程语言不同的是,Python 并不是同时运行的,而是轮流运行。这是因为 Python 中有一种全局解释器锁( Global Interpreter Lock,GIL)机制。这一点,以及 threading 库在 我撰写的关于 Python 并发性的文章 有详细的解释。

我们得到的结论是,线程对于 IO 密集型的软件有很大的影响,但对 CPU 密集型的软件毫无用处。

这是为什么呢?很简单。当一个线程在等待来自网络的答复时,其他线程可以继续运行。如果你要执行大量的网络请求,线程可以带来巨大的差异。如果你的线程正在进行繁重的计算,那么它们只是等待轮到它们继续计算,线程化只会带来更多的开销。

4. 使用 Asyncio

Asyncio 是 Python 中一个相对较新的核心库。它解决了与线程相同的问题:它加快了 IO 密集型软件的速度,但这是以不同的方式实现的。我将立即坦承我并非 Python 的 asyncio 拥趸。它相当复杂,特别是对于初学者来说。我遇到的另一个问题是, asyncio 库在过去几年中有了很大的发展。网上的教程和示例代码常常已经过时。不过,这并不意味着它就毫无用处。

5 同时使用多个处理器

如果你的软件是 CPU 密集型的,你通常可以用一种可以同时使用更多处理器的方式重写你的代码。通过这种方式,你就可以线性地调整执行速度。

这就是所谓的并行性,但并不是所有的算法都可以并行运行。例如,简单的将递归算法进行并行化是不可能的。但是几乎总有一种替代算法可以很好地并行工作。

使用更多处理处理器有两种方式:

  1. 在同一台机器内使用多个处理器和 / 或内核。在 Python 中,这可以通过 multiprocessing 库来完成。
  2. 使用计算机网络来使用多个处理器,分布在多台计算机上。我们称之为分布式计算。

这篇 关于 Python 并发性的文章 侧重于介绍如何在一台机器的范围内扩展 Python 软件的方法。它还介绍了 multiprocessing 库。如果你认为这是你需要的资料,一定要去看看。

与 threading 库不同, multiprocessing 库绕过了 Python 的全局解释器锁。它实际上是通过派生多个 Python 实例来实现这一点的。因此,现在你可以让多个 Python 进程同时运行你的代码,而不是在单个 Python 进程中轮流运行线程。

提高python代码运行效率的一些建议

multiprocessing 库和 threading 库非常相似。可能出现的问题是:为什么还要考虑线程呢?答案是可以猜得到的。线程是“轻量”的:它需要更少的内存,因为它只需要一个正在运行的 Python 解释器。产生新进程也还有其开销。因此,如果你的代码是 IO 密集型的,线程可能就足够好了。

一旦你实现了软件的并行工作,那么在使用 Hadoop 之类的分布式计算方面就前进了一小步。通过利用云计算平台,你可以相对轻松地进行扩展规模。例如,你可以在云端中处理大型数据集,并在本地使用结果。使用混合操作的方式,你可以节省一些资金,因为云端中的算力非常昂贵。

总结

总结起来就是:

  • 首先考虑优化你的算法和代码。
  • 如果原始速度可以解决你的问题,请考虑使用 PyPy。
  • 对 IO 密集型软件使用 threading 库和 asyncio 。
  • 使用 multiprocessing 库解决 CPU 密集型问题。
  • 如果所有这些措施还不够的话,可以利用 Hadoop 等云计算平台进行扩展规模。

以上就是提高python代码运行效率的一些建议的详细内容,更多关于提高python代码运行效率的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
黑科技 Python脚本帮你找出微信上删除你好友的人
Jan 07 Python
Python常用知识点汇总
May 08 Python
Python实现句子翻译功能
Nov 14 Python
python监测当前联网状态并连接的实例
Dec 18 Python
Python利用字典破解WIFI密码的方法
Feb 27 Python
Python3常用内置方法代码实例
Nov 18 Python
Python栈的实现方法示例【列表、单链表】
Feb 22 Python
Django之choices选项和富文本编辑器的使用详解
Apr 01 Python
keras和tensorflow使用fit_generator 批次训练操作
Jul 03 Python
用Python的绘图库(matplotlib)绘制小波能量谱
Apr 17 Python
python基于tkinter制作下班倒计时工具
Apr 28 Python
详解Python flask的前后端交互
Mar 31 Python
Python爬取微信小程序Charles实现过程图解
Sep 29 #Python
Python Charles抓包配置实现流程图解
Sep 29 #Python
python和node.js生成当前时间戳的示例
Sep 29 #Python
python实现图书馆抢座(自动预约)功能的示例代码
Sep 29 #Python
Python 下载Bing壁纸的示例
Sep 29 #Python
pycharm 2020 1.1的安装流程
Sep 29 #Python
利用django创建一个简易的博客网站的示例
Sep 29 #Python
You might like
PHP中4种常用的抓取网络数据方法
2015/06/04 PHP
浅谈javascript的数据类型检测
2010/07/10 Javascript
JavaScript(js)设置默认输入焦点(focus)
2012/12/28 Javascript
js过滤HTML标签以及空格的思路及代码
2013/05/24 Javascript
javascript 获取网页标题代码实例
2014/01/22 Javascript
js获取页面传来参数的方法
2014/09/06 Javascript
浅谈JavaScript字符串与数组
2015/06/03 Javascript
javascript+HTML5的canvas实现七夕情人节3D玫瑰花效果代码
2015/08/04 Javascript
JS简单生成两个数字之间随机数的方法
2016/08/03 Javascript
AngularJs Dependency Injection(DI,依赖注入)
2016/09/02 Javascript
React学习笔记之高阶组件应用
2018/06/02 Javascript
详解vue-cli3 中跨域解决方案
2019/04/10 Javascript
vue-cli3 DllPlugin 提取公用库的方法
2019/04/24 Javascript
详解基于Vue的支持数据双向绑定的select组件
2019/09/02 Javascript
详解Vue3 Composition API中的提取和重用逻辑
2020/04/29 Javascript
echarts柱状图背景重叠组合而非并列的实现代码
2020/12/10 Javascript
JavaScript WeakMap使用详解
2021/02/05 Javascript
Python 调用DLL操作抄表机
2009/01/12 Python
Python赋值语句后逗号的作用分析
2015/06/08 Python
浅谈使用Python变量时要避免的3个错误
2017/10/30 Python
Django REST framework 单元测试实例解析
2019/11/07 Python
django之导入并执行自定义的函数模块图解
2020/04/01 Python
PIL.Image.open和cv2.imread的比较与相互转换的方法
2020/06/03 Python
如何在网站上添加谷歌定位信息
2016/04/16 HTML / CSS
使用 HTML5 Canvas 制作水波纹效果点击图片就会触发
2014/09/15 HTML / CSS
美国女性服饰销售网站:Nasty Gal(坏女孩)
2016/07/26 全球购物
加拿大最大的五金、家居装修和园艺产品商店:RONA
2017/01/27 全球购物
如何转换一个字符串到enum值
2014/04/12 面试题
linux面试题参考答案(9)
2015/01/07 面试题
员工自我鉴定
2013/10/09 职场文书
计生专干事迹
2014/05/28 职场文书
员工教育培训协议书
2014/09/27 职场文书
上课玩手机的检讨书
2014/10/01 职场文书
政府个人对照检查材料思想汇报
2014/10/08 职场文书
政府会议通知范文
2015/04/15 职场文书
vue基于Teleport实现Modal组件
2021/05/31 Vue.js