基于 Pre-commit 的 Python項目代碼風格統一實踐

背景信息

統一代碼風格首先需要定義參照的規范,每個團隊可能會有自己的規范,我們選擇的規范是 yapf + mypy + isort,如果保證所有的研發人員都遵循相關規范呢?

  1. 鼓勵 IDE 中對應的插件的安裝,通過直接對應的插件,在編寫代碼階段就能實時發現不符合規范的情況,修改成本最低;
  2. 通過 Pre-commit 在創建 commit 時執行檢查,并進行必要的自動格式化,提供統一的規范約束,成本次之;
  3. 在發起 Pull-Request 時拉取代碼執行檢查,并異步返回檢查結果,成本稍高一些,但是功能也更完備一些,不僅能可以進行靜態檢查,也可以進行必要的自動化測試;

而本次主要介紹的就是基于 Pre-commit 進行必要的代碼檢查與格式化,期間遇到一些問題,整理出來幫助后人少踩坑吧。

Pre-commit 簡單介紹

Pre commit 是 git 提供的預提交機制,可以在創建 commit 之前執行預定義的鉤子程序,從而方便執行必要的代碼檢查。

而在實踐中可能會需要執行大量的鉤子程序,如果來管理這些鉤子程序呢,Pre-commit 就是其中一個應用較多的框架,通過這個框架可以比較方便地管理大量的預提交鉤子程序,這樣簡化了維護成本。如何來使用 Pre-commit 框架呢?

  1. 安裝 Pre-commit 框架,一般情況下 pip 安裝下即可;
  2. 在工程中添加 .pre-commit-config.yaml 文件,需要安裝的鉤子程序都是維護在這個配置文件中的;
  3. 通過 pre-commit install 安裝對應的鉤子程序;

后續在創建 commit 時就會依次執行安裝好的鉤子程序,如果不符合鉤子程序對應的規范,就會檢查失敗,commit 無法創建,類似如下所示:
請添加圖片描述

Pre-commit 的使用主要關注的是配置文件 .pre-commit-config.yaml 的定義,配置文件的一個簡單例子如下所示:

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooksrev: v2.3.0hooks:-   id: check-yaml-   id: end-of-file-fixer-   id: trailing-whitespace-   repo: https://github.com/psf/blackrev: 22.10.0hooks:-   id: black

在配置文件中主要關注下面的字段:

  • repo:指定鉤子對應的代碼庫
  • rev:指定代碼倉庫對應的版本
  • hooks:指定代碼庫中需要用到的鉤子

Pre-commit 支持的完整的所有的代碼倉庫與對應的鉤子見官方 Supported Hooks

具體實踐

項目中使用的是 yapf + isort + mypy 的組合,之前已經在工程中安裝完成,包管理是使用 poetry 實現的,因此格式化工具對應的配置都是定義在 poetry.yaml 文件中的。本次使用 Pre-commit 期望也能直接使用原有格式化工具的配置,從而保證與定義好的規范保持一致。

yapf

本次在 Pre-commit 中使用 yapf 時,配置文件 .pre-commit-config.yaml 中的定義如下所示:

- repo: https://github.com/google/yapfrev: 'v0.31.0'hooks:- id: yapf

在 Pre-commit 中使用 yapf 時,報錯 toml package is needed for using pyproject.toml as a configuration file,但是直接調用 yapf 時可以正常執行的。

定位問題后發現,Pre-commit 安裝的鉤子是放在獨立的虛擬環境里面的,這個虛擬環境中沒有對應的 toml 包,因此執行 yapf 報錯

解決方案就是通過 additional_dependencies 指定對應的包依賴,這樣依賴的包才能被正確安裝,修改配置后即可正確執行,最終配置如下:

- repo: https://github.com/google/yapfrev: 'v0.31.0'hooks:- id: yapfadditional_dependencies: [toml]
isort

isort 主要用于進行代碼 import 順序的調整,定義的配置如下所示:

- repo: https://github.com/PyCQA/isortrev: 5.12.0hooks:- id: isort
mypy

項目中主要是使用 mypy 進行靜態的代碼檢查,初始定義的配置如下所示:

- repo: https://github.com/pre-commit/mirrors-mypyrev: 'v0.910'hooks:-   id: mypy

增加測試代碼進行驗證后發現問題很多:

  1. Pre-commit 中使用的 mypy 雖然是增量提交的,但是很多沒有修改的文件中的問題也被提醒出來,導致需要修改的文件特別多;
  2. 原本在 pyproject.toml 中 mypy 配置中明確排除掉的文件中的問題也會上報出來,而手工執行 mypy 是被正常忽略的;

對于問題 1 定位后發現 mypy 增量提交時會遞歸對 import 導入的文件同時進行靜態類型檢查,從靜態類型工具的角度是可以理解的,因為需要確認調用方和定義的函數類型是否一致,因此需要遞歸導入和檢查,但是這樣就會導致增量提交失去意義,對于已有工程而言在發起新提交時會需要修改大量的文件。

問題 2 的原因其實也與這個 import 循環導入有關,mypy 配置時通過 exclude 參數排除掉文件,在 mypy 全量檢查時會跳過,但是如果是增量提交,通過 import 導入的文件依舊會執行靜態類型檢查,此時 exclude 就沒辦法排除掉了

對于提到的這兩個問題,github 上有不少人給 mypy 上報了異常,甚至原有 exclude 參數不能排除掉 import 文件的機制設計,有開發者提出了 force exclude 的 PR,但是截止目前而言,這個想法沒有被現有 mypy 的維護者認可

從 mypy 維護者的解釋來看,mypy 作為靜態類型檢查工具,是需要結合執行上下文來盡可能發現不符合靜態類型定義的問題,force exclude 會導致沒辦法根據調用上下文發現類型不匹配的問題,mypy 就失去了意義。從 mypy 作為靜態類型檢查工具的角度來看,這個解釋沒有太大問題,但是在 Pre-commit 中使用 mypy 確實就會出現上面所說的那些問題,導致根本不可用。因此 mypy 維護者提出了 建議解決方案,方案的解決思路如下:

  1. mypy 開啟對整個工程的代碼檢查,即傳遞參數 pass_filenames: false,不要使用增量式傳遞新增文件的方式;
  2. pre-commit 使用獨立的虛擬環境去安裝 mypy,會導致第三方庫的類型檢查失效,建議直接使用原有運行虛擬環境中的 mypy 進行檢查,通過 language: system 進行配置;

最終配置定義如下:

- repo: https://github.com/pre-commit/mirrors-mypyrev: 'v0.910'hooks:- id: mypyentry: mypy .language: systempass_filenames: false

測試確實能解決掉原先 exclude 不生效的問題,但是由于目前是全量檢查,因此需要先對工程中原有的不符合 mypy 規范的進行了修復后,再開啟對應的 mypy 檢查。雖然解決方案不夠完美,需要先進行一輪全局的修復,但是修復后工作良好。

總結

通過上面的配置調整,最終在工程中正常配置了 Pre-commit,保證了團隊代碼風格的一致性,Pre-commit 通過將必要的規范限制在開發環境,保證了對開發人員的統一風格約束,從而提升整體代碼質量,有興趣可以嘗試一下

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/17169.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/17169.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/17169.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

bootstrap實現天平效果

之前提到了,最近,孩子的幼兒園讓家長體驗“半日助教活動”,每個家長需要講授15-20分鐘的課程。作為一名程序員,實在沒有能教的課程,只能做了一個小游戲,帶著小朋友們熟悉數字。 在上一章博客中&#xff0c…

【讀書】讀書筆記——理科生的視角:底層邏輯+數學之美

1,底層邏輯1(看清這個世界的底牌) 劉潤 著 0)什么是底層邏輯? 底層邏輯是:事物之間共同點、變化背后不變的東西事;看清事物的本質,才能在復雜變化中從根本上解決問題。 1&#x…

【Java繼承】(超級詳細!!!)

【Java繼承】(超級詳細!!!) 1、 繼承的概念2 、繼承的語法3、 父類成員訪問3.1 子類中訪問父類的成員變量3.2 子類中訪問父類的成員方法 4、 super關鍵字5 、子類的構造方法6、 繼承關系上的執行順序7、protected 關鍵…

ubuntu20.04安裝后配置:wifi、屏幕亮度、Nvidia驅動等

文章目錄 一、安裝時最好用英語,否則Downloads等home下文件夾是中文二、安裝后開機無法進入系統圖形界面三、清理不必要軟件,更新系統四、屏幕亮度、Nvidia驅動五、wifi 一、安裝時最好用英語,否則Downloads等home下文件夾是中文 安裝完再在…

error: ‘address‘ in ‘class school‘ does not name a type school:: address = “

錯誤代碼 class school{ public:string name;static string address; public:static string getAddress(){return address;} };school::address "南京路";原因 school::address “南京路”;前面未加類型,導致編譯錯誤 解決 class school{ public:stri…

選項卡式小部件QTabWidget

文章目錄 1. 詳細介紹2. 常用屬性3. 信號4. 常用函數5. 官方示例Tab Dialog QTabWidget提供一堆選項卡式小部件。 1. 詳細介紹 選項卡式部件提供一個選項卡欄和一個用于顯示與每個選項卡相關的頁面的頁面區域。 默認情況下,選項卡欄顯示在頁面區域上方,…

Vue.js - 計算屬性與偵聽器 【0基礎向 Vue 基礎學習】

文章目錄 計算屬性 computedcomputed 的使用方法computed 與 method 的區別計算屬性完整寫法 watch 偵聽器(監視器)簡單寫法 → 簡單類型數據,直接監視完整寫法 → 添加額外配置項 計算屬性 computed computed 的使用方法 **概念&#xff1…

web題解,基礎知識鞏固(qsnctf)

1.文章管理系統 1)打開題目,把它頁面翻完了,沒看懂它有啥用 2)看了看源碼,也是一樣的,沒找到有用的東西 3)想著可能還是在隱藏文件里找,那我就直接用dirsearch掃掃看 4)…

初識C++ · 模擬實現vector

目錄 前言: 1 部分簡單函數的實現 2 push_back和pop_back 3 reserve和resize 4 Print_vector 5 insert和erase 6 拷貝構造 7 構造 8 賦值 9 memcpy的問題 10 迭代器失效 前言: 繼上文模擬實現了string之后,接著就模擬實現vector&…

DataFrame—數據匯總9

s3.sort_index() 文章最前: 我是Octopus,這個名字來源于我的中文名--章魚;我熱愛編程、熱愛算法、熱愛開源。所有源碼在我的個人github ;這博客是記錄我學習的點點滴滴,如果您對 Python、Java、AI、算法有興趣&#xf…

MyBatis復習筆記

3.Mybatis復習 3.1 xml配置 properties&#xff1a;加載配置文件 settings&#xff1a;設置駝峰映射 <settings><setting name"mapUnderscoreToCamelCase" value"true"/> </settings>typeAliases&#xff1a;類型別名設置 #這樣在映射…

如何去除視頻上的文字?免費無痕去水印分享!視頻制作良器!

對于需要進行二次創作的視頻素材&#xff0c;去除原有的文字可以提供一個更加干凈的畫布&#xff0c;方便創作者在其基礎上進行新的創作和編輯。同時&#xff0c;去除文字后的視頻也更方便分享到各種平臺&#xff0c;避免因為平臺對文字的限制而導致視頻無法發布或傳播。 要去除…

Kotlin 標準函數 with、run、apply 的定義和使用

Kotlin 標準函數 with、run、apply 的定義和使用 1. with 函數 定義&#xff1a; with 函數允許你在一個對象的上下文中執行一個 lambda 表達式&#xff0c;而不需要在 lambda 表達式中重復引用該對象。 kotlin.internal.InlineOnly public inline fun <T, R> with(r…

云計算期末復習(1)

云計算基礎 作業&#xff08;問答題&#xff09; &#xff08;1&#xff09;總結云計算的特點。 透明的云端計算服務 “無限”多的計算資源&#xff0c;提供強大的計算能力 按需分配&#xff0c;彈性伸縮&#xff0c;取用方便&#xff0c;成本低廉資源共享&#xff0c;降低企…

python 3.10 install on centos

CentOS 7 安裝 Python 3.10_yum python3.10-CSDN博客

Homebrew安裝mysql之后,啟動和使用MySQL服務:

啟動MySQL服務&#xff1a; brew services start mysql 手動啟動服務&#xff1a; mysql.server start 例如&#xff1a; mysql.server start Starting MySQL .. SUCCESS! 停止 MySQL服務&#xff1a; brew services stop mysql 或者 mysql.server stop 重啟MySQL服務&a…

IDEA使用Maven打包項目的所有的依賴

要使用 Maven 命令將 Spring Boot 項目的依賴打包到 lib 文件夾中&#xff0c;你可以在終端中運行以下命令&#xff1a; mvn dependency:copy-dependencies -DoutputDirectory./lib這個命令會將項目的所有依賴&#xff08;包括運行時依賴&#xff09;復制到當前目錄的 lib 文件…

Windows操作系統基本知識整理

目錄 引言 一、Windows操作系統的發展歷史 1.1 Windows 1.0到Windows 3.0 1.2 Windows 95到Windows Me 1.3 Windows NT到Windows 2000 1.4 Windows XP到Windows 7 1.5 Windows 8到Windows 10 二、Windows操作系統的核心組件 2.1 內核 2.2 文件系統 2.3 圖形用戶界面&…

內網橫向移動小補充 --->PTK

大家別急&#xff0c;我的基于資源的約束性委派攻擊還在寫&#xff0c;這個東西一時半會講不清楚&#xff0c;所以我在這里先來補充一點橫向移動以前沒說好的東西&#xff01;&#xff01;&#xff01; 在更啦&#xff0c;別催啦~~~~ 還記得我之前在內網滲透里面講過這個PTK&a…

亞馬遜云主管馬特·加爾曼面臨壓力,致力于在人工智能領域趕超競爭對手

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…