Python 程式碼的質量控制之 flake8 & Pylint

浮生若夢的程式設計發表於2019-03-04

為什麼需要質量控制工具

無需多言,我偏執地認為,所有動態語言寫成的專案,都應該使用 XXLint 之類的工具,該暴露的錯誤能提前就提前。

甚至,所有專案在 commit 之前都需要做兩件事情:

  1. lint 檢查
  2. UT

動態語言是邊解釋邊執行,缺乏編譯期。這是劣勢也是優勢,這是優勢也是劣勢。

Python 中,常用的質量控制工具就是:pytest(或其他),Pylint,flake8(較強大),本文介紹後兩者。

如何使用

如果沒有提及這兩款工具,那麼一個自然的想法是:給定原始碼目錄 src,工具要能夠檢查 src 所有符合要求的檔案,即:

flake8 $OPTIONS $src
複製程式碼

事實上,這些工具就是這麼工作的。指定檔案或目錄,然後它幫你檢查。

與工作流的整合

命令列的使用尚且簡單,不過沒有人這麼使用(這仍然是重複性勞動),冗長的文件也沒幾個人喜歡閱讀,所以最佳實踐才是重點。

我個人的最佳實踐是:與 git pre-commit 結合,如果檢查不過,就不讓 commit。

思路大概有如下幾種:

  1. pre-commit 使用 bash 指令碼編寫,呼叫對應命令執行
  2. pre-commit 使用 Python 指令碼編寫(個人比較偏好這種,主要是對 Shell 實在愛不起來)

如果使用 Python 指令碼,我比較喜歡使用 Fabric 來組織我的程式碼( Fabric 簡單小巧,夠用)。

比如專案結構一般會這樣:

.pylintrc
.flake8
fabfile.py
project/
tests/
docs/
複製程式碼

那麼 fabfile.py 的內容大致就是


@task
def runpylint():
    local(`pylint project/`)
    
@task
def runflake8():
    local(`flake8 project/`)
    
@task
def runpytest():
    pass

@task
def runfabfile():
    execute(runpylint)
    execute(runflake8)
    execute(runpytest)
    
手動執行: 
    fab runfabfile
複製程式碼

那麼 .git/hooks/pre-commit 的內容就是:

#!/usr/bin/env bash

function _runfab() {
    fab runfabfile
    
    if [[ "$?" == 0 ]]; then
        return 0
    else
        return 1
    fi
}

_runfab
複製程式碼

總結

工具的使用,自然不是重點,原則才是。我覺得比較重要的幾條原則是:

  1. 一切從嚴。比如 Pylint 的 C 級別錯誤也不能放過(不過有些檢查確實多餘,可以 disable 掉,但是 disable 的數量應當越少越好)。
  2. 不僅與 pre-commit 結合,而且與 CI 工具結合,不留死角。

相關文章