isort 是一個 Python 套件兼命令列工具,可以幫開發者自動排序 Python imports,以符合 PEP 8 規範。這種排序也可以讓程式碼更加易讀且易於維護。

之前已有數篇文章介紹過,可參考本站的「isort 標籤頁」。

isort 會自動將 import 分為「Python 標準函式庫」、「第三方套件」、「本地模組」等三大區塊,並依字母順序排列,同時為你在三個區塊之間空一行

isort 本地模組排序錯誤

isort 有一個 bug(我也不確定是不是 bug),就是對於本地模組的「排序判斷」,有可能發生錯誤。

這會造成什麼結果?通常的影響是,本來應該排在第三區塊的 import,排到第二區塊去了。總之就是 import 放錯了區塊。

這樣除了不符合 PEP 8 規範,更重要的是,它還可能對開發者造成「誤導」。而且會使用 isort 的人,往往就是在乎 import 排序的人,當然不能接受這樣的錯誤。

VS Code 解法

我第一次發現這個問題是在 VS Code 的整合界面,在自動格式化時,發現本地模組被錯誤地分類到了第三方模組

很自然的輸入關鍵字,比如「isort wrong order」,你能找到這篇 issue:

往下滑,很快你就得到了答案,在settings.json加入以下設定:

1
2
3
"python.sortImports.args": [
"--src=${workspaceFolder}",
],

不過上面是以前的做法,現在 isort 有獨立套件,所以應該用下面的設定:

1
2
3
"isort.args": [
"--src=${workspaceFolder}",
],

pyproject.toml 與 pre-commit 設定

在有了 pre-commit 以後,僅設定 VS Code 是不夠的。因為即使 IDE 格式化的結果正確,若未設定 pre-commit 的 isort hook,仍可能受到阻擋,造成衝突。

另外,在團隊開發時,使用pyproject.toml來設定 isort 參數,明顯比所有成員各自設定其自己的 VS Code 更加可行。

所以我們需要設定前述二者的 isort 參數。

不過,仔細想想,顯然pyproject.toml和 pre-commit 的 isort 設定,不會是上述的settings.json的照抄。因為它們根本不知道${workspaceFolder}是什麼。

想必有別的做法。

pyproject.toml

設定如下,使用src_paths = ["."]

1
2
3
[tool.isort]
line_length = 100
src_paths = ["."] # <--- 這裡

pre-commit

.pre-commit-config.yaml設定如下,使用--src=.

1
2
3
4
5
6
7
8
- repo: https://github.com/PyCQA/isort
rev: 5.11.5
hooks:
- id: isort
exclude: migrations/
args:
- --line-length=100
- --src=. # <--- 這裡

基本上都是用「.」來代表專案根目錄。

附帶一提

值得注意的是,如果 VS Code 有設定 isort,那這個設定將優先於pyproject.toml這樣的邏輯我不太能理解,因為理論上愈小範圍應該要優先適用才對。讀者使用時,可留意一下兩者的設定是否存在衝突。

我自己平常都是透過settings.json設定 isort,至於pyproject.toml,則是給團隊其餘沒有設定 VS Code 的人使用的。

不過,總的來說,團隊協作還是盡可能透過「專案設定檔」如pyproject.toml來設定這些工具的參數會比較妥當。一旦有變動,也能在 Git 同步後,全體立即適用。