大厂Data+Agent 秘籍:腾讯/阿里/字节解析如何提升数据分析智能。 了解详情
写点什么

论 Python 语言的三大短板与解决办法

  • 2019-08-22
  • 本文字数:3554 字

    阅读完需:约 12 分钟

论 Python 语言的三大短板与解决办法

多年以来,Python 语言一直受到性能、应用程序打包以及项目管理三大问题的困扰。好在,解决方案即将到来。


虽然 Python 诞生距今已经有 30 年左右,但就在过去几年当中,其受欢迎程度开始快速提升并达到旷古烁今的地步。当下,唯有 Java 及 C 等顶尖高手能够与之匹敌。另外,Python 的普及程度超越了传统编程语言,目前在教学与学术研究当中成为最优编程方法、理想的软件开发起点以及几乎一切技术堆栈的重要组成部分。


遗憾的是,旺盛的人气也放大了 Python 语言的固有缺陷。与其优点一样,Python 也有着不少天生顽疾——性能、应用程序打包与交付,以及项目管理困难,一直是支持者心中永远的痛。虽然这些并不算什么致命缺陷,只能说是 Python 普及道路上的一点障碍;但随着 Julia、Nim、Rust 以及 Go 等其他竞争语言的崛起,解决这些问题已经成为 Python 的燃眉之急。


在本文中,我们将探讨 Python 程序员面对的三大主要挑战,以及 Python 自身、第三方 Python 工具以及库开发者们尝试解决这些挑战的具体方法。

Python 多线程与速度

问题:Python 的总体性能较慢,有限的线程与孱弱的多处理能力成为其未来发展的主要障碍。


Python 长期以来一直更重视编程速度,而非运行速度。考虑到很多开发者习惯于利用 C 或 C++编写高速外部库(例如 NumPy 或者 Numba)以执行 Python 下的性能密集型任务,这样的权衡似乎也没什么大不了。但问题在于,Python 的开箱性能仍然落后于其它语法同样简单、但能够编译为机器码的语言,例如 Nim 或者 Julia。


Python 当中历史最悠久的性能问题之一,在于其对多核心或处理器的资源使用能力不佳。虽然 Python 确实具有线程功能,但却仅限于单一核心。此外,Python 也会尝试通过启动其运行时的子实例以支持多处理,但是针对这些子进程结果的调度与同步往往效率不高。


解决方案:目前,还没有某一种自上而下的整体性解决方案,能够直接搞定 Python 的性能问题。不过,现在已经出现了一系列用于加速 Python 的尝试,其各自都在特定领域做出了一定改进。


下面来看例子:


  • 改善 CPython 的内部行为。 CPython 改进带来了幅度有限但却覆盖面广泛的加速效果。例如,Python 3.8 的 Vectorcall 协议为 Python 对象带来了更快的调用约定。虽然改进效果不算显著,但足以带来具有可测量且可预测的性能提升,而且完全不会破坏向下兼容性;此外,现有 Python 应用程序可直接受益,无需任何代码重写。

  • 改进 CPython 的子解释器功能。 Python 解释器实例的新编程接口现在可以时在各解释器之间实现优雅的数据共享,从而实现多核处理。现在,这项提案已经确定将在 Python 3.9 中面世,相信其还将在后续版本中继续发挥重要作用。

  • 改进多个进程之间的对象共享。Python 当中的多处理机制会为每个核心启动一个新的解释器实例,用以获取最佳性能;但当多个解释器尝试对同一内存对象进行操作时,大部分性能提升都会瞬间作废。目前,以 SahredMemory 类以及新的 pickle 协议为代表的新功能,可以减少解释器之间数据传递所需要的复制或者序列化过程,从根本上消除相关性能问题。


在 Python 之外,也有不少外部项目带来了新的性能提升方法——但同样仅限于特定问题:


  • PyPy。另一种 Python 解释器,PyPy 能够将 Python 即时编译为本机机器码。它在纯 Python 项目当中发挥出色,现在也能很好地兼容比较流行的二进制相关库——例如 NumPy。但其一般更适合长期运行的服务,而非一次性应用程序。

  • Cython。 Cython允许用户逐步将 Python 代码转换为 C 代码。该项目最初是专为科学与数值计算所设计的,但却能够在大多数场景下起效。Cython 最大的缺点在于语法,其使用了独有的语法设置,且转换只能单向进行。Cython 最适合处理“热点”部分代码,这种有针对性的优化方式往往比应用程序整体优化要更合理、也更可行。

  • Numba。 Numba 的即时编译功能可以面向选定功能将 Python 代码编译为机器码。与 Cython 类似,Numba 同样主要用于科学计算,其比较适合就地运行而非对代码进行重新发布。

  • Mypyc。Mypyc 项目目前仍在开发当中,其希望将带有 mypy 类型注释的 Python 代码转换为 C 代码。Mypyc 很有前途,因为其使用到 Python 中的众多原生类型,但目前距离生产应用还有很长的路要走。

  • 经过优化的 Python 发行版。某些第三方 Python 版本(例如英特尔的 Python 发行版)拥有可充分发挥英特尔处理器扩展(例如 AVX512)优势的数学与统计库。需要注意的是,尽管其能够显著加快特定数学函数的执行速度,但却无法实现全面的速度提升。


有经验的 Python 程序员一定还会提到全局解释器锁(GIL)的问题,其负责对指向对象的访问进行序列化,以确保不同线程不会彼此影响到对方的工作负载。从理论上讲,放弃 GIL 可以提高性能。然而,无 GIL Python 基本上丧失了向下兼容能力(特别是在 Python C 扩展方面)。因此到目前为止,所有移除 GIL 的尝试要么已经走进死胡同,要么反而降低了 Python 的性能。


目前另一个正在推进的 Python 计划有望解决不少速度方面的问题,即重构 Python 内部的 C API 实现。众长远来看,提升 API 集的有序程度可以带来诸多性能改进:重新设计或者剔除 GIL、提供可实现强大即时编译的 hook、在解释器实例之间使用更好的数据联合方法等等。

Python 打包与独立可执行文件

问题:即使是在 30 年之后,Python 仍然没能拿到理想的方法,用以将程序或脚本转换为自打包可执行文件,并轻松部署在多种平台之上。


虽然这一目标已经有办法实现,但依靠的主要是第三方工具,而非 Python 的原生功能——此外,其使用难度也不太友好。


最具知名且最受支持的当数PyInstaller,它能够打包多种广受喜爱的高人气第三方扩展,例如 NumPy。不过PyInstaller必须与这些第三方扩展手动保持同步,而这在 Python 的庞大生态系统中无疑是一项艰巨的任务。此外,PyInstaller会生成超大的应用程序包,因为其中捆绑有程序 import 语句中所要求的全部内容,而且并不确定在运行时究竟会用到哪些组件。此外,PyInstaller也无法实现跨平台应用程序打包;我们必须在目标部署平台上进行包创建。


解决方案: 我对 PyInstaller 抱有充分的尊重,但我们可能还需要一套 Python 原生解决方案——无论是内置形式,还是通过标准库提供。它应当允许开发人员以独立二进制文件的形式将 Python 应用程序打包并交付至各类常见的平台。理想情况下,这款内置的打包器应该利用运行时代码覆盖率信息确保仅打包所需的库(而非所有内容),并能够自动与其余 Python 库保持同步。


目前还没有这样的解决方案存在,但关于如何构建此类工具的提示倒是所在多有。PyOxidizer 项目使用 Rust 语言生成能够嵌入 Python 的二进制文件,并将此作为创建独立 Python 应用程序的一种方法。虽然该项目尚处于起步阶段,距离成为完整的应用程序交付方案还有很长的路要走,但这足以证明 Python 生态系统之外的成果也许会成为解决挑战的关键。

Python 安装、软件包管理与项目管理

问题: 有些使用体验太过复杂——对,说的就是为专业级 Python 项目设置工作区、目录结构与基本架构;管理与项目相关的环境、软件包及依赖项;以可重复方式重新分配项目来源;并一次又一次不断进行这个过程。


Rust 与 Go 这两种语言,在初始设计阶段就强调提供一种单一且规范的项目设置方式,并允许开发者在整个生命周期之内对其进行轻松管理。Rust 与 Go 开发人员虽然因此牺牲掉了一定程度的灵活性,但却换来了良好的一致性、可预测性以及可管理性。


Python 提供的安装、软件包以及项目管理工具与方法,随着时间推移而不断积压,并成为 30 年发展周期中的一笔重大负担。其中有用于软件包管理的 pip、用于创建虚拟环境的 venv/virtualenv、用于元管理的 virtualenvwrapper 与 Pipenv、用于生成项目依赖性的 pip-tools、以及用于创建 Python 代码发行版的 distutils 与 setuptools 等。此外,还有负责定义项目其它部分的 setup.py、requirements.txt、setup.cfg、MANIFEST.in 以及 Pipfile 等等。


解决方案: 同样的,我们需要取代这如同一团乱麻的工具与流程大杂烩,由 Python 核心开发团队拿出一套规范性的解决方案,同时确保其能够优雅地迁移一切利用现有方法开发出的项目。当然,这是个很难解决的挑战,但随着 Python 语言变得越来越重要,我们必须努力让它成为一款易于上手、维护简单、一致性强且友好舒适的编程工具。


目前这方面工作已经有所进展。根据 PEP 518 提案,Python 的 build 依赖项被合并为 pyproject.toml 文件格式。而像poetry 这样的第三方工具虽然只能打包现有工具,但已经体现出一体化管理产品的样貌。随着时间的推移,其中一种解决方案也许会脱颖而出、受到整个社区的关注,并成为客观层面甚至是范式性的处理标准。


原文链接:


https://www.infoworld.com/article/3429565/3-major-python-shortcomingsand-their-solutions.html?upd=1566265910128


2019-08-22 10:507617

评论 1 条评论

发布
用户头像
与其想尽办法去处理这些 Python 问题,还不如选择另一个更适合的语言,成本更低。
2019-08-22 11:42
回复
没有更多了
发现更多内容

开创人工智能产业新未来!7月8日昇思生态论坛与你相约广州

科技热闻

中文版Postman?功能真心强大!

Liam

Java 开发者工具 Postman 后端开发 程序员进阶

不要再手动批量替换了,使用python AST模块批量替换

阿呆

Python AST 批量替换

如何组织一场实战攻防演练

穿过生命散发芬芳

攻防演练 7月月更

企业数字化转型之路,从这里开始

天翼云开发者社区

数字化转型 云存储

【愚公系列】2022年7月 Go教学课程 004-Go代码注释

愚公搬代码

7月月更

让开发效率飞速提升的跨端方案

Geek_99967b

小程序 跨端 小程序容器

牛客java选择题每日打卡Day7

京与旧铺

7月月更

RedHat7.4配置yum软件仓库(RHEL7.4)

Albert Edison

7月月更

Linux RedHat7.4更换阿里云yum源

Albert Edison

7月月更

7000+字图文并茂解带你深入理解java锁升级的每个细节

华为云开发者联盟

Java 开发 华为云

一文读懂简单查询代价估算

华为云开发者联盟

数据库 后端 查询引擎

集合处理的利器

技术小生

java8 7月月更

systemd-resolved 开启 debug 日志

程序员与厨子

ubuntu 运维 DNS systemd-resolved

分布式算法入门之 Paxos 算法

宇宙之一粟

Basic paxos 7月月更

XaaS 陷阱:万物皆服务(可能)并不是IT真正需要的东西

雨果

云服务 xaas DaaS 本地服务

使用 RepositoryProvider简化父子组件的传值

岛上码农

flutter ios 安卓 移动端开发 7月月更

【刷题记录】1. 两数之和

WangNing

7月月更

场景化面试:关于分布式锁的十问十答

面试官问

分布式锁

MySQL数据库索引教程(超详细)

Albert Edison

7月月更

一朵云开启智慧交通新未来

天翼云开发者社区

区块链 大数据 物联网

AI金榜题名时,MLPerf榜单的份量究竟有多重?

脑极体

Ubuntu 20.04 安装 Chisel

贾献华

7月月更

微服务链路风险分析

阿泽🧸

7月月更 链路风险分析

5. 数据访问 - EntityFramework集成

MASA技术团队

C# .net 微软 后端 Framework

国内低代码开发平台靠谱的都有哪些?

AIRIOT

低代码 物联网 低代码,项目开发

Spring你牛个啥,我承认刚才说话我声音有点大

zxhtom

7月月更

华为云ModelArts文本分类–外卖评论

逝缘~

深度学习 华为云 7月月更

企业级数据安全,天翼云是这样理解的

天翼云开发者社区

数据安全

鱼和熊掌可以兼得!天翼云弹性裸金属一招鲜!

天翼云开发者社区

服务器 弹性扩容

MMAP

北洋

Andriod 7月月更

论 Python 语言的三大短板与解决办法_语言 & 开发_Serdar Yegulalp_InfoQ精选文章