博客,python & 类型
2020/05/28
Python SDK 类型更改
Beam Python 近期增加了对 Python 3 类型注释的支持和集成,以提高代码清晰度和类型正确性检查。继续阅读以了解最新情况。
Python 支持函数上的类型注释(PEP 484)。静态类型检查器(如 mypy)用于验证对这些类型的遵守。例如
def f(v: int) -> int:
return v[0]
在上述代码上运行 mypy 将给出错误:Value of type "int" is not indexable
。
我们最近在 2 个方面对 Beam 做了一些更改
在整个 Beam 中添加类型注释。类型注释使像 Beam 这样庞大而复杂的代码库更容易理解和在您喜欢的 IDE 中导航。
其次,我们添加了对 Python 3 类型注释的支持。这允许 SDK 用户在一个地方指定 DoFn 的类型提示。我们还扩展了 Beam 对 typing
模块类型的支持。
有关更多背景信息,请参阅:确保 Python 类型安全。
Beam 已键入
与 DoFn 内部的新的类型注释支持相一致,我们投入了大量时间将类型注释添加到 Beam python 代码本身。有了它,我们开始使用 mypy(一个静态类型检查器)作为 Beam 代码审查流程的一部分,这确保了更高质量的贡献和更少的错误。类型注释在整个 Beam 中添加的额外上下文和见解对所有 Beam 开发人员、贡献者和最终用户都有用,但对新加入项目的开发人员特别有利。如果您使用的 IDE 理解类型注释,它将提供比以前更丰富的类型补全和警告。您还可以使用 IDE 检查 Beam 函数和转换的类型,以更好地了解它们的工作原理,这将简化您自己的开发。最后,一旦 Beam 完成注释,最终用户将能够从在他们自己的管道和自定义转换上使用静态类型分析中受益。
新的注释方式
Python 3 语法注释
在 Beam 2.21(BEAM-8280)中,您将能够使用 Python 注释语法来指定输入和输出类型。
例如,这种新的形式
class MyDoFn(beam.DoFn):
def process(self, element: int) -> typing.Text:
yield str(element)
等效于此
@apache_beam.typehints.with_input_types(int)
@apache_beam.typehints.with_output_types(typing.Text)
class MyDoFn(beam.DoFn):
def process(self, element):
yield str(element)
新形式的优点之一是,您可能已经在与 mypy 等静态类型检查器一起使用它,从而免费获得额外的运行时类型检查。
此功能将默认启用,并且将有 2 种机制来禁用它
- 在管道构建之前调用
apache_beam.typehints.disable_type_annotations()
将完全禁用此新功能。 - 用
@apache_beam.typehints.no_annotations
装饰一个函数将告诉 Beam 忽略它的注释。
Beam 的 with_input_type
、with_output_type
方法和装饰器的使用仍然有效,并且优先于注释。
侧边栏
您可能会问:我们不能使用 mypy 来类型检查 Beam 管道吗?这并非如此的原因有很多。
- 管道在运行时构建,并且可能依赖于只有在该时间才知道的信息,例如配置文件或数据库表架构。
- PCollection 没有必要的类型信息,因此 mypy 将它们视为有效地包含任何元素类型。这在将来可能会改变。
- 使用 lambda 的转换(例如:
beam.Map(lambda x: (1, x)
)无法使用 PEP 484 正确注释。但是,Beam 会尽力尝试从字节码分析输出类型。
键入模块支持
Python 的 typing 模块定义了类型注释中使用的类型。这就是我们所说的“原生”类型。虽然 Beam 有自己的键入类型,但它也支持原生类型。虽然 Beam 和原生类型都受支持,但对于新代码,我们建议使用原生键入类型。原生类型具有这些,因为它们受到更多工具的支持。
在处理 Python 3 注释语法支持时,我们还发现了并修复了原生类型支持问题。可能仍然存在错误和不受支持的原生类型。如果您遇到问题,请告知我们。