部落格、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
。
我們最近在 Beam 中進行了 2 個方面的變更
在整個 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 會將它們視為有效包含任何元素類型。這未來可能會改變。
- 使用 lambdas 的轉換(例如:
beam.Map(lambda x: (1, x)
) 無法使用 PEP 484 正確註解。但是,Beam 會盡最大努力嘗試從位元組碼分析輸出類型。
模組類型支援
Python 的 typing 模組定義了類型註解中使用的類型。這就是我們所稱的「原生」類型。雖然 Beam 有自己的類型類型,但也支援原生類型。雖然支援 Beam 和原生類型,但對於新程式碼,我們鼓勵使用原生類型類型。原生類型受到其他工具的支援。
在處理 Python 3 註解語法支援時,我們也發現並修正了原生類型支援的問題。可能仍然存在錯誤和不受支援的原生類型。如果您遇到問題,請告訴我們。