亚马逊AWS官方博客

Python 3.8 已经来了,你准备好了吗?

前言

上一周,我在亚马逊 AWS 官方博客发了一篇介绍 Deep Java Library (DJL)一个面向 Java 的深度学习开发库的文章。

没有等来预期的鲜花和掌声,收到的第一个反馈来自一个年轻的业内精英,他的问题居然是 –

 

只是为了证明尚未老矣仍能饭否,临时起意草就一篇急就章,内容围绕不那么中古的语言 – Python。

 

Python 3.8

过去几年,在编程语言领域 Python 可谓大红大紫。开发者对于这门语言的热情也推动了Python 语言的的快速发展。自2015年开始,Python 几乎以每年一个主要版本的速度不断的演进。

主版本 发布日期 结束支持日期 结束安全修复日期
3.5 2015-09-13 2017-08-08 2020-09-13
3.6 2016-12-23 2018-12-24 2021-12
3.7 2018-06-27 2020-06-27 2023-06
3.8 2019-10-14 2021-04 2024-10
3.9 2020-10-05 2022-05 2025-10

来源:https://en.wikipedia.org/wiki/History_of_Python

 

就在三个月前,我们注意到在Python 官网上悄然发布了最新的稳定版本Python 3.8。如果只是从数目字来看似乎只有0.1的变化,但如果仔细的阅读PEP文档,还是要不禁为Python 3.8 叫一声好!

 

Python 3.8 的新特性

说起来这次发布的新版本从2019年夏天就开始就有了测试版本,短短的几个月后在 2019年10月14日第一个官方的稳定版本就已经准备好了。这足以看出Python 社区对这个新版本的热情。而这个稳定的版本的出现,可以让我们即刻就开始使用 Python 的新特性并从最新的改进中获益。

 

来源:https://www.python.org/downloads/release/python-380/

 

与目前使用最为广泛的Python 3.7对比起来,Python3.8 的变化主要表现在这几个方面 –

  • PEP 572,赋值表达式
  • PEP 570,仅限位置的形参
  • PEP 587,Python 初始化配置(改进的嵌入)
  • PEP 590,Vectorcall:用于 CPython 的快速调用协议
  • PEP 578, Python 运行时审计挂钩
  • PEP 574,具有外部数据缓冲区的 pickle 协议 5
  • 与打字相关:PEP 591(最终限定词)、PEP 586(文字类型)和 PEP 589(TypedDict)
  • 并行文件系统缓存,用于编译的字节码
  • 调试版本使用与发布版本使用相同的 ABI
  • f – 字符串支持的便捷性 = 用于调试的说明符
  • 在finally:块中,continue现在是合法的
  • 在 Windows 上,默认 asyncio 事件循环现在是 ProactorEventLoop
  • 在 macOS 上,spawn 启动方法默认使用 multiprocessing
  • multiprocessing 现在可以使用共享内存段来避免进程之间的pickle开销
  • typed_ast 被合并回了 CPython
  • LOAD_GLOBAL 速度加快了 40%
  • pickle 现在默认使用协议 4,提高了性能

 

在这些变化当中,给我留下深刻印象的有这样几个特性 –

 

  • 赋值表达式

Python 3.8 这一次增加了一个新的语法 :=,用来将值赋给一个表达式中的变量。这个新方法也被亲切地称为 “海象运算符” (walrus operator),因为这个表达式看起来像是海象的眼睛和象牙。具体用法是这样的

之前

现在- 海象运算符

>>> walrus = True

print(walrus)

>>> print(walrus := True)

True

 

以前,赋值只能以语句形式提供。对于Python 3.8,它可以在列表生成(list comprehensions)和其他表达式上下文中使用。

 

  • 仅限位置的形参

仅位置参数通过引入新的函数参数语法 “/“ 来指示某些函数参数必须在位置上指定且不能用作关键字参数,从而为库的开发者提供了更多控制权。

在描述API时,可以使用它们更好地表达预期的用法,并允许API以安全,向后兼容的方式发展。 它们还使Python语言与现有文档以及各种“内置”和标准库函数的行为更加一致。

定义

调用

def f(a, b, /, c, d, *, e, f):

print(a, b, c, d, e, f)

    f(10, 20, 30, d=40, e=50, f=60)

 

  • 代码调试中支持的 f-string

f-string(或者称为「格式化字符串」)是在 Python 3.6 版本中加入的特性。虽然这一特性非常方便,但是开发者发现 f-string 对调试没有实际的帮助。因此,Eric V. Smith 为 f-string 添加了一些语法结构,使其能够用于调试。于是, Python 3.8增加了在f-string内部使用赋值表达式的能力,需要注意的是f-string是从左到右计算的。

之前

现在- 海象运算符

>>> city = “London”
>>> f”Living in {city} is amazing“‘Living in London is amazing

>>> import math

>>> radius = 3.8

>>>f”With a diameter of {( diameter := 2 * radius)}, the circumference is {math.pi * diameter:.2f}

With a diameter of 7.6 the circumference is 23.88

 

  • System V风格共享内存带来的性能的提升

在版本3.8中,Python开始支持System V风格的共享内存。这种支持允许创建可以在Python进程之间共享的内存段,因此有助于在进程之间共享数据时避免(反)序列化的成本。这个变化引入了一个新的管理器multiprocessing.managers.SharedMemoryManager。该管理器允许基于管理器来访问此共享内存功能。 此外,还引入了一个名为multiprocessing.shared_memory 的新程序包。 这个程序包包含SharedMemory和ShareableList类。 前一个类提供对共享内存的“原始”访问,而后一个类则通过将其抽象为Python中的列表来提供对共享内存的访问。可以设想,这个特性对于进程间通讯的效率的提升将是显而易见的。

 

如果有兴趣,可以体验一下这段代码带来的两种场景的对比

 

源代码:https://gist.github.com/rvprasad/899ad680b70cfecb81718161798f3862/raw/5719d5a28dd21e871c5a485ec41193bdfef40595/test_mulitprocessing_shared_memory.py

 

安装 Python 3.8

Python 3.8 已经是一个稳定的版本,并且许多使用广泛的Python 包已经兼容于这个最新的版本。在我初步测试中,无论AWS 的Python 开发包boto3,还是NumPy,Django等等都可以很好的运行于Python 3.8 之上。如果需要自行体验这个最新版本,首先需要的就是在系统中安装Python 3.8。

 

  • Ubuntu 18.04

在Ubuntu 18.04 官方的“仓库”中已经提供了Python 3.8 的程序包。我们只需要用这样一个简单的命令就可以完成安装 –

sudo apt install -y python3.8

如果考虑到开发中的需要,还可以安装这几个包 –

sudo apt install -y python3.8-dev python3.8-venv python3.8-doc

安装后的Python 版本是这样的 –

 

  • Amazon Linux 2

目前Amazon Linux 2 的官方”仓库” 以及EEPL的“仓库”中都没有提供Python 3.8 的安装包。不得已,我们只能自己动手。不过不用担心,我为大家准备了一个一键安装。安装脚本的内容是这样的 –

 

 

这个脚本看起来啰嗦,其实完成下载、编译、安装的过程却很快。在我的一台m5a.2xlarge 的实例上,仅仅用了大约28秒的时间就完成了全部过程。安装完成以后,我们就得到了完整的Python3.8 环境,可以让我们尽情体验这些新的特性了。

 

 

Python 3.8 的另一种玩法 – Amazon Lambda

 

上面提到的关于Python 3.8 的一切,其实与以往众多的Python新版本别无两样。但是斗转星移,我们今天使用Python 来开发已经远远不止这样的方式。这些新的方法你也许听说过,其中就有大热的AWS Lambda。可以说AWS Lambda 的横空出世,给了应用开发、部署以及管理带来全新的内容。 对于我们今天的话题Python 3.8 来说,AWS Lambda 也给出一种新的选择。

 

就在Python3.8 发布之后的第35天,Amazon 发布了AWS Lambda 对于Python 3.8的支持。我们可以将Python函数部署到AWS Lambda 上,利用Python 3.8 运行时来执行我们的Python 代码。

 

在考虑程序的兼容性的前提下,我们可以在众多Python 运行时的环境中进行选择。在程序的稳定性、性能、新特性等之间作出最适当的选择。目前在AWS Lambda 上提供的Python 运行时有这样几个版本 –

 

我应该升级到 Python 3.8 吗?

很简单,如果你打算尝试上文介绍的 Python 3.8 的任何新功能,那么就应该升级到 Python 3.8。像 Pyenv 和 Anaconda 这样的工具也可以很容易地安装多个版本的 Python,也包括了Python3.8。或者,你也可以运行官方的 Python 3.8 Docker 容器。这可能是另一个最简便的体验的方式

 

不过,是否应该将生产环境升级到 Python 3.8 呢?这需要考虑你的项目是否依赖 Python 3.8 的新功能以及程序的兼容性的问题。例如Nvidia 的TensorRT 的Python程序包目前还无法支持Python 3.8 。至于AWS Lambda,我建议我们首先进行的是兼容性的测试,之后考虑一个周密的升级的计划。当然升级版本以运行 Python 3.8 可以说是非常安全的,而且我们的代码也能利用新版本的特性来进行优化。考虑到历史上Python2 到Python3 的升级带来的巨大代价,我们还是尽早的开始考虑Python版本的渐进升级的策略吧。

 

 

本篇作者


费良宏

费良宏,AWS Principal Developer Advocate。在过去的20多年一直从事软件架构、程序开发以及技术推广等领域的工作。他经常在各类技术会议上发表演讲进行分享,他还是多个技术社区的热心参与者。他擅长Web领域应用、移动应用以及机器学习等的开发,也从事过多个大型软件项目的设计、开发与项目管理。目前他专注与云计算以及互联网等技术领域,致力于帮助中国的 开发者构建基于云计算的新一代的互联网应用。