Pyright 上手指南:Python 型別檢查的新選擇
文章目錄
如〈Python 套件管理器 uv 介紹——與 Poetry 比較〉一文中所述,最近我開始了一個新的 side project。
我打算好好利用這個專案,練習並實踐那些,在工作中無法盡情揮灑,或想學習但是還用不到的新技術。包括後端、AI、DevOps。
為了嘗試不同的開發體驗,從框架到工具都有所更新:
- 因應 AI 時代,後端框架改用 FastAPI——輕量,且非同步支援佳。
- 套件管理器從 Poetry 換成 uv——快,就是快。
而型別檢查器——本文的主角,則從 Mypy 改為 Pyright。
這不是一時興起的炫技選擇,而是一連串有意識的技術決策:選擇那些效能更好、體驗更佳,並且有長期潛力的替代方案。
Pyright,就是其中之一。
為什麼需要型別檢查?
如果你對 Python 的「型別檢查」議題還不熟,歡迎參考我之前寫的「Mypy 三部曲」,其中對 Python type hints 與型別靜態分析工具做了深入說明。
Type hints 歷經多代 Python 發展至今,已趨於成熟。但它在實際專案中的流行程度,恐怕還不算高。
甚至直白地說,對部分 Python 開發者而言,可能:
- 沒聽過。
- 知道但無感。
這正是本文要努力的目標——讓更多人加入撰寫 Python type hints 的行列🔥😎
型別檢查的價值
簡言之,型別檢查不是為了「多寫幾行」程式碼,而是為了讓 IDE 幫我們多想一點、早點報錯,減少 runtime 的 trial & error。
它能比單元測試讓你更早、更容易發現語法錯誤。
要做到這點——讓 Python 像「半個靜態語言」一樣可靠。我們除了需要好好寫 type hints,還要搭配「型別檢查器」(type checker)。
對我來說,type hints 與型別檢查,已經從「選配」變成「開發必需品」,就像 linter、formatter 一樣。
在擁抱 type hints 成為開發習慣後,接下來就是要選擇一個好用的「型別檢查器」來幫我們把關。
除了老牌的 Mypy 之外,有沒有其它選擇呢?
答案是肯定的,這就是本文接下來要介紹的主角——Pyright。
Pyright 簡介——為什麼選它?
如〈Python type checker:Mypy 介紹〉中所言,Mypy 誕生於 2012 年——這甚至比 Python 正式導入 type hints 還早!
作為第一個被廣泛採用的型別檢查工具,它為 Python 型別註解奠定了基礎,但同時也背負了早期設計的限制與歷史包袱。
Pyright 誕生於 2019 年,由微軟開發,設計之初即參考 TypeScript 的靜態型別系統,並針對 IDE 整合與效能優化。它更年輕、設計更現代——後發者優勢。
Pyright 的三大優勢
Pyright 有以下三大賣點。
1. 效能極快,檢查大型專案也很輕鬆
Pyright 以高效能著稱。
Pyright is a full-featured, standards-based static type checker for Python. It is designed for high performance and can be used with large Python source bases.
使用 TypeScript 實現並運行於 Node.js 上,號稱效能比 Mypy 快 5 倍以上,特別適合大型 Python 專案。
2. 能進行「型別推斷」
Pyright 能對「未型別註解」的程式碼進行型別推斷(type inference),嘗試分析並提供檢查結果。
這使得它對舊有的程式碼專案(無型別註解)依然有效。
不過,Pyright 的型別檢查效果在「有明確型別註解時」會更好,且對於未註解的程式碼,檢查深度可能不如有註解的程式碼嚴謹。
型別推斷的真正意義
不過說真的,型別推斷和「好好寫 type hints」的核心精神是有些違背的,把它當成一個 bonus 就好。
我認為 type hints 的本質是在實踐 Zen of Python 中的:
Explicit is better than implicit
而 Pyright 的型別推斷則是為了兼容舊有程式碼,讓你可以慢慢補上 type hints。
3 .與 VS Code 的整合幾乎是零設定
直接內建於 Pylance!
用 VS Code 寫 Python,一定會裝 Pylance,相當於當年 Windows 綁 IE 的概念XD
只需要你在 VS Code 的 UI 把型別檢查打開即可。如下圖:
這樣就能享受 Pyright 的型別檢查功能,不需要額外設定。
看完 Pyright 的優勢,接下來和老牌的 Mypy 比較一下。
Mypy vs Pyright 重點比較
兩者雖然都是 Python 的靜態型別檢查工具,但設計哲學與使用體驗有所不同。
特性 | Mypy | Pyright |
---|---|---|
開發者 | Python 官方支援(部分) | Microsoft(富爸爸) |
執行速度 | 較慢,尤其在大型專案中 | 非常快 |
Type Checking 嚴格性 | 偏保守,有些 type error 不會抓 | 更嚴格,預設就更接近 TypeScript 的風格 |
支援型別提示(PEP) | 完整支援 PEP 484 等標準 | 同樣完整,但對 edge cases 處理得更細緻 |
自動化工具整合 | 較傳統、整合需要設定 | 用 VS Code 即可獲得完整體驗 |
錯誤訊息易讀性(重要) | 普通,訊息有時不夠具體 | 很清楚,並且能指出路徑與具體型別差異 |
我認為比較重要的是「執行速度」與「錯誤訊息易讀性」這兩點。
介紹完背景,現在可以來實作了。
安裝 Pyright
如前所述,Pyright 是使用 TypeScript 寫成,所以原則上要使用 npm 來安裝——聽到這裡你可能就不是很想用了XD
別擔心,Pyright 當然提供了 Python wrapper 版本,因此也可以直接用 Python 套件方式安裝,推薦使用 uv 並安裝到 dev group:
1 | uv add --dev pyright |
或者更穩健的做法:
1 | uv add --dev pyright[nodejs] |
這個套件實際上是在背後幫你自動安裝了 Pyright 的 Node.js 執行檔與環境,並提供了一個 Python wrapper。
而上述兩種指令的區別,可以參考留言區的討論。
安裝套件的意義
裝是裝了,但這個工具基本上不是給開發者直接使用的。主要用途在:
- 作為 pre-commit 執行檔。
- CI 的環境安裝。
至於開發時,Pylance 本來就安裝了 Pyright,自然就會顯示錯誤提示。
關於設定檔
如同 Mypy 使用 mypy.ini
或pyproject.toml
。
你可以透過pyrightconfig.json
或pyproject.toml
來客製化 Pyright 的檢查行為。
其中pyrightconfig.json
是原生的設定檔格式,而pyproject.toml
則是後來才追加的。
如果專案中同時存在pyrightconfig.json
和pyproject.toml
,Pyright 會優先使用pyrightconfig.json
的設定。
兩者目前基本上可以視為等價,所以要選擇哪一種格式,主要取決於你希望 Pyright 的設定檔要獨立還和其它工具放在一起。
我暫時選擇獨立,採pyrightconfig.json
,內容如下:
1 | { |
此外,一旦 VS Code 偵測到有設定檔存在,預設的檢查等級就會是standard
——不管你 VS Code 本來怎麼設定。
此時最好就明示設定typeCheckingMode
,如上所示。
Pyright 的三種等級
Pyright 提供三種檢查等級:
basic
:適合大部分實務開發,檢查範圍涵蓋常見錯誤,擾動小。standard
:預設值,比 basic 略為嚴格。strict
:嚴格,適合對型別非常重視的專案或團隊。
想知道這三個等級的具體區別,可以參考官方文件的這個對照表。
個人認為basic
或standard
就已足夠,能在不影響開發節奏的情況下提供良好的型別保障。
整合 pre-commit 與注意事項
我習慣將型別檢查加入 pre-commit hook,確保每次 commit 都經過檢查。
但是,不可否認,型別檢查器的 hook 設定比 linter、formatter 要來得講究許多!
因為它需要完整的執行環境——包括相依套件,不像 linter 只需對程式碼直接進行檢查即可。
所以設定上會麻煩一些,之前使用 Mypy 就踩過不少坑。
從結論上來說,把 hook 設定為「本地」會單純得多。適合單人開發的 side project,我的設定如下:
1 | - repo: local |
其中name
欄位的名稱可以自訂,id
部分因為是 local hook,也能夠自訂。entry
的路徑則要看專案虛擬環境所在。
值得一提的是,上述 hook 設定還得搭配pyrightconfig.json
中的:
1 | "venvPath": ".", |
才能正常執行。
使用 Remote Hook
用遠端倉庫的 hook 也行,但常見的做法我試不成功,以下設定則可以 work:
1 | - repo: https://github.com/RobertCraigie/pyright-python |
但一樣要搭配上述的pyrightconfig.json
設定內容。
或寫成pyproject.toml
格式如下:
1 | [tool.pyright] |
更多細節可參考上述 hook 的 GitHub 主頁介紹。
CI 設定待補
目前還沒有實作 CI,之後實作會再補上設定檔。
結語:新工具、新氣象
我感覺光是寫完這篇文章,又讓我對 Pyright 的了解增進許多XD
其實,無論是 Mypy 或 Pyright,還是其它工具。願意寫 type hints、進行型別檢查,就已經是很好的實踐。
工具只是細節上的分歧,並不影響大局。
我們最終想成為的,是優秀的開發者——問題解決者。