iT邦幫忙

2024 iThome 鐵人賽

DAY 24
0
DevOps

我獨自升級:從水管工走向 DataOps系列 第 24

【Day 24】Data Pipeline 測試 - Python linter feat. Ruff

  • 分享至 

  • xImage
  •  

前世今生

Ruff 最早是由 Charlie Marsh 創立的開源 Python linter,目前已成立 Astral 公司負責維運,Ruff 是使用 Rust 語言編寫,目的是為了提高 Python 開發的效率和速度,並整合多種不同的 linter 工具,如 Flake8、isort 和 Black,進而降低檢查次數,Ruff 除了是 linter,還能涵蓋自動格式化和型別檢查等等,因其速度而受社群歡迎,許多知名開源專案都有使用 Hugging Face、Airflow、FastAPI 等等,到底有哪些採用可以看這裡

  • 主要特色 : 快,超級快,下圖為官方提供的比較圖,比其他 linter 快 10 ~ 100 倍,而且 Ruff 的主要目標是持續往 linter + formatter 前進,/images/emoticon/emoticon08.gif,不要想說現在才 v0.6.9(4天前發布),其實已經開發了一陣子,更新也很頻繁,使用人數也很多,v0.1.0 是 2023/10發布的,在 v0.1.0 之前的已經發布了 v0.0.292 這麼多次~

https://ithelp.ithome.com.tw/upload/images/20241008/20135427l6LqGWeXcX.png

圖片來源:Ruff 官方文件

Formatter 與 Linter 有差嗎?

1. 目的不同

Linter:主要關注程式碼品質、效能和潛在問題
Formatter:主要關注代碼外觀、排版和一致性

2. 自動化不同

Linter:通常需要開發者根據提示進行修改
Formatter:可以自動執行所有更改

3. 自訂設定不同

Linter:通常有很多可自訂的設定規則
Formatter:通常採用"固執己見"的方式,設定選項較少

4. 工具範例

Linter:ESLint(用於 JavaScript)和 Pylint(用於 Python)
Formatter:Prettier(用於多種語言,如 JavaScript、TypeScript)和 Black(用於 Python)

5. 可能情境

Linter:在 Python 中使用了一個未定義的變數,Pylint 會檢查你的程式碼並警告你這個變數未被定義,需要手動回去修正這個問題,定義變數或調整邏輯。Linter 專注於程式碼的正確性和潛在問題,避免程式執行中斷。

Formatter:在 Python 中的縮排、括號、空格不一致,Black(常見的 Formatter 工具)會自動調整這些格式。即使執行結果正確,Formatter 仍會確保你的代碼在排版上保持一致性,讓團隊成員之間的協作更順暢。比如,如果你不小心在一行中使用了過多的空白,Black 會幫你自動修正這些不必要的格式問題。

Ruff 實作範例

ruff check 檢查

例如我在 dbt/ 檢查 dags/simple_task_group.py 的程式碼,執行方式就是 ruff check XX.py

$ ruff check dags/simple_task_group.py

也可以直接檢查特定資料夾下的所有程式,例如 dags/ 資料夾以下的所有檔案

$ ruff check dags/*.py

如果我引入了一個 task 的 decorator,卻沒有使用,就會被偵測出來

https://ithelp.ithome.com.tw/upload/images/20241008/20135427sHMbciLc7W.png

錯誤訊息已經明確說明問題了

Remove unused import: `airflow.decorators.task`

ruff rule 確認錯誤

但如果還是看不懂,可以針對這個錯誤代碼,使用ruff rule {錯誤代碼}去查詢

$ ruff rule F401

就可以直接看到詳細的說明和範例

# unused-import (F401)
Derived from the **Pyflakes** linter.
Fix is sometimes available.
## What it does
...

## Why is this bad?
...
## Example

import numpy as np  # unused import
def area(radius):
    return 3.14 * radius**2

Use instead:

def area(radius):
    return 3.14 * radius**2

ruff check --fix 修復

執行 --fix 來修復程式碼

$ ruff check --fix dags/*.py

ruff check --watch 即時檢查

--watch 算是我比較常用的,一邊寫程式也可以開一個 terminal 視窗確認是否有問題,每次儲存都會即時檢查,有問題馬上調整,不然常常最後寫完改 linter 也是很煩/images/emoticon/emoticon06.gif

$ ruff check --watch dags/*.py

linter+format 二合一:ruff format 直接調整格式

最終目標當然是讓大家也不使用 Black 啦~/images/emoticon/emoticon01.gif

$ ruff format folder/file.py
$ ruff format folder/

自訂 linter 設定

可以透過 ruff.toml 來設定,如果有用 poetry 來管理環境也可以直接設定在 pyproject.toml 當中,我基本上還是用虛擬環境搭配 requirements.txt

調整過程中,也可以直接用線上工具來測試設定

# 設定要檢查的 Python 版本
[tool.ruff]
target-version = "py39"  # 其他版本範例: 'py310', 'py311'

# 指定要包含的規則
select = [
    "E",  # PEP8 錯誤
    "F"   # Pyflakes 檢查
]

# 指定要忽略的規則 (避免不需要的錯誤或警告)
ignore = [
    "E501",  # 忽略行長度超過規範 (79 字元) 的錯誤
    "W503"   # 忽略違反行內換行規則
]

# 設定最大行數長度(若沒有忽略 E501)
line-length = 88

# 排除特定目錄
exclude = [
    "tests/",
    "docs/",
    "__pycache__/",
    ".git/"
]

這裡只是提供一個簡單的範例,想知道還有哪些可以設定,可以看官方的詳細說明

Ruff in vscode

  1. 安裝 vscode 插件 ruff

  2. .vscode/setting.json 中加上這段

{
    ...,
    "[python]": {
        "editor.defaultFormatter": "charliermarsh.ruff" 
    },
    ...
}

當處理 Python 文件時,Ruff 會被用作編輯器的默認格式化工具。

結語

明天就會講到 Data Quality 的測試了/images/emoticon/emoticon11.gif


上一篇
【Day 23】Data Pipeline 測試 - SQL linter feat. SQLFluff
下一篇
【Day 25】Data Pipeline 測試 - Data Quality feat. dbt test
系列文
我獨自升級:從水管工走向 DataOps30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言