Python高效代码实践:性能、内存和可用性
点击上方Python知识圈,设为星标
回复100获取100题PDF
阅读文本大概需要 5 分钟
占用尽可能小的内存、执行地更快、看起来整洁、文档正确、遵循标准风格指南,并且易于被新开发者理解。
1. 尽量不要对内存置之不理
使用 format 而不是 “+” 来生成字符串 —— 在Python中,str 是不可变的,所以每对连接都必须将左、右字符串复制到新的字符串中。如果连接长度为10的四个字符串,则将复制(10+10) + ((10+10)+10) + (((10+10)+10)+10) = 90 个字符,而不是 40 字符。随着字符串数量和大小的增加,事情会变得越来越糟。Java 有时将一系列的连接转换为使用StringBuilder 来优化这种情况,但是 CPython 没有。因此,建议使用 .format 或 % 语法。如果您不能在 .format 和 % 之间选择,请查看 这个有趣的 StackOverflow 问题[2] 。
定义 Python 类时使用槽(slots)。您可以通过将类中的
__slots__
设置为固定的属性名称列表,来告诉 Python 不要使用动态字典,只为一组固定的属性分配空间,从而消除了为每个对象使用一个字典的开销。在 这里[3] 阅读更多关于槽的内容。您可以通过使用内置的模块(如 resource 和 objgraph)来跟踪对象级别的内存使用情况。
在 Python 中管理内存泄漏可能是一项艰巨的任务,但幸运的是有一些工具(如 heapy)用于调试内存泄漏。Heapy 可以与 objgraph 一起使用来观察 diff 对象的分配随时间而增长。Heapy 可以显示哪些对象占用最多的内存。Objgraph 可以帮助您找到反向引用,以明白为什么它们不能被释放。您可以在 这里[4] 阅读更多关于在Python中诊断内存泄漏的信息。
2. Python2 还是 Python3
3. 写出美丽的代码
PEP-8 风格指南
Python 习语和效率
Google Python 风格指南
使用静态代码分析工具
正确地文档说明代码
该功能的一行概要。
如果适用的话,提供交互示例。这些可以让新开发人员参考,以快速了解功能的使用和预期的输出。您也可以使用 doctest 模块来确保这些示例的正确性(以测试方式运行)。请参阅 doctest 文档 中的示例。
参数文档(通常一行描述参数及其在函数中的作用)
返回类型的文档(除非您的函数没有返回任何内容!)
4. 提高性能
多进程,而不是多线程
操作系统(通过多进程)
一些调用您的 Python 代码的外部应用程序(例如 Spark 或 Hadoop)
您的Python代码所调用的代码(例如,您可以让 Python 代码调用C函数,来执行昂贵的多线程内容)。
使用最新版本的 Python:
这是最直接的方法,因为新的更新通常包括对已经存在功能性能方面的增强。尽可能使用内置函数:
这也符合 DRY 原则 —— 内置函数由世界上一些最好的 Python 开发人员仔细设计和审查,所以它们通常是最好的方式。考虑使用 Ctypes:
Ctypes 提供了一个在 Python 代码中调用 C 共享函数的接口。C 是一种更接近机器级别的语言,与 Python 中的类似实现相比,代码执行速度更快。使用 Cython:
Cython 是一种 Python 语言的超集,允许用户调用 C 函数并具有静态类型声明,最后生成一份更简单的最终代码,可能会执行得快得多。使用 PyPy:
PyPy 是具有 JIT(即时)编译器的另一个 Python 实现,可以使您的代码执行更快。虽然我从未尝试过 PyPy,但它也声称会减少程序的内存消耗。像 Quora 这样的公司实际上在生产环境中使用 PyPy。设计与数据结构:
适用于各种语言。确保您正在为目标使用正确的数据结构,在正确的地方声明变量,明智地利用标识符范围,并在任何有意义的地方缓存结果等。
5. 分析您的代码
memory_profiler 是一个用于监视进程内存消耗的Python模块,它能对 Python 程序的内存消耗进行逐行分析。
objgraph 能显示前N个占用 Python 程序内存的对象、在一段时间内删除或添加的对象以及脚本中给定对象的所有引用。
resource 为程序测量和控制系统资源使用提供了基本机制。该模块的两个主要用途包括限制资源分配和获取有关资源当前使用情况的信息。
6. 测试和持续集成
测试
nose —— 可以运行 unittest 测试,并具有较少的样板。
pytest —— 也运行unittest测试,更少的样板,更好的报告和很多很酷,额外的功能。
测量覆盖度
持续集成
在现实环境中运行测试。有些情况下,测试在某些架构上通过,而在其他架构上失败。CI 服务可以让您在不同的系统架构上运行测试。
对您的代码库执行覆盖度约束。
构建和部署您的代码到生产环境(您可以在不同的平台上这样做)
References
[1]
https://jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/[2]
https://stackoverflow.com/questions/5082452/string-formatting-vs-format[3]
https://stackoverflow.com/questions/472000/usage-of-slots[4]
https://chase-seibert.github.io/blog/2013/08/03/diagnosing-memory-leaks-python.html[5]
http://deeplearning.net/software/theano/tutorial/python-memory-management.html[6]
http://python-future.org/compatible_idioms.html[7]
https://www.youtube.com/watch?v=KOqk8j11aAI&t=10m14s[8]
https://docs.python-guide.org/writing/documentation/[9]
https://pythonguidecn.readthedocs.io/zh/latest/[10]
https://stackoverflow.com/questions/67299/is-unit-testing-worth-the-effort[11]
https://pythontesting.net/start-here/往期推荐 01 02 03
↓点击阅读原文查看pk哥原创视频