Sử dụng pre-commit để thực thi PEP8 chỉ trong 3 bước

Tác giả: Kiên (Software Engineer | CAI)

Đảm bảo code tuân thủ đầy đủ các quy tắc được đề xuất trong PEP8 là một điều vô cùng quan trọng, đặc biệt là trong làm việc nhóm, khi mà yếu tố dễ đọc, dễ hiểu, và dễ bảo trì code được đặt lên hàng đầu. Dẫu vậy, đây vẫn là một quá trình thủ công và có thể tốn nhiều thời gian của bạn. Vậy có cách nào nhanh chóng và dễ dàng hơn không?

Trong số Tech Blog này, chúng mình sẽ cùng nhau tìm hiểu chi tiết về cách sử dụng pre-commit để kiểm tra và tự động sửa các vấn đề liên quan đến PEP8 trước khi commit code vào Git repository.

Lưu ý: Nội dung bài viết này hướng tới những độc giả đã có kiến thức cơ bản về PEP8 và Git. Nếu bạn chưa từng sử dụng 2 công cụ trên, vui lòng tìm hiểu thêm tại các nguồn sau:

Giới thiệu về pre-commit

pre-commit là một thư viện Python được sử dụng để quản lý các Git hooks một cách hiệu quả. Git hooks là những scripts tự động chạy mỗi khi có một sự kiện nào đó (ví dụ như commit code hay push code) diễn ra trong Git repository.

Với pre-commit, bạn có thể dễ dàng khai báo những hooks mà bạn muốn chạy khi commit code. Ví dụ, những hooks này có thể kiểm tra xem code đã đúng định dạng PEP8 chưa. Nếu chưa, quá trình commit code sẽ thất bại và bạn sẽ nhận được danh sách các lỗi cần khắc phục. Quá trình commit code chỉ thành công khi không có lỗi nào xảy ra.

Cài đặt và cấu hình pre-commit

Bước 1: Cài đặt pre-commit

Để cài đặt pre-commit, bạn có thể sử dụng pip, trình quản lý gói của Python:

$ pip install pre-commit

Bạn có thể kiểm tra kết quả của việc cài đặt pre-commit thông qua dòng lệnh pre-commit --version. Nếu việc cài đặt thành công, bạn sẽ nhìn thấy version hiện tại của pre-commit.

$ pre-commit --version
pre-commit 3.2.1

Bước 2: Tạo file cấu hình cho pre-commit

Tạo một file .pre-commit-config.yaml trong thư mục gốc của dự án với nội dung như sau:

repos:
  - repo: https://github.com/psf/black
    rev: 23.3.0
    hooks:
      - id: black
  - repo: https://github.com/PyCQA/isort
    rev: 5.12.0
    hooks:
      - id: isort
  - repo: https://github.com/PyCQA/flake8
    rev: 6.0.0
    hooks:
      - id: flake8

Trong file này, chúng ta sẽ cần cung cấp những thông tin sau:

  • repo là URL của repository chứa các hook mà bạn muốn dùng.
  • rev là một phiên bản cụ thể của repository.
  • hooks là danh sách các hook bạn muốn cài đặt.

Trong ví dụ này, chúng mình dùng kết hợp 3 hooks: black, isortflake. Cụ thể:

  • black sẽ phát hiện và tự động sửa những lỗi PEP8 liên quan tới khoảng trắng, cách dòng.
  • isort sẽ phát hiện và tự động sửa những lỗi PEP8 về thứ tự import.
  • flake sẽ phát hiện ra những lỗi mà 2 hooks trên không xử lý được ví dụ như lỗi unused import hay lỗi undefined name.

Bước 3: Cài đặt Git hook

Để sử dụng pre-commit tự động mỗi lần commit code vào repository, bạn cần chạy lệnh pre-commit install trong thư mục gốc của dự án:

$ pre-commit install
pre-commit installed at .git/hooks/pre-commit

Chạy pre-commit

Giả sử, trong dự án của bạn đang có một file app.py với nội dung:

# This is a sample Python script.
import requests
import os

if __name__ == "__main__":
    # the required first parameter of the 'get' method is the 'url':
    response = requests.get("https://w3schools.com/python/demopage.htm")
    abc="123"
    # print the response text (the content of the requested file):
    print(response1.text)

File app.py trên có 4 lỗi PEP8 như sau:

  1. Unused import ở dòng số 3 (import os). Thư viện os được import vào nhưng không được sử dụng trong file app.py.
  2. Thứ tự import cũng không đúng ở dòng số 2 và 3 vì os là thư viện built-in của Python nên cần được import trước một thư viện bên thứ 3 như requests.
  3. Thiếu khoảng trắng ở dòng số 8 (abc="123"). PEP8 yêu cầu một khoảng trắng ở trước và ở sau dấu bằng (=).
  4. Cuối cùng, biến response1 chưa được khai báo trước khi dùng ở dòng số 10 (print(response1.text)).

Để kiểm tra và tự động sửa những lỗi PEP8 bên trên, bạn chạy lệnh pre-commit run --all-files trong thư mục code dự án của mình nhé.

$ pre-commit run --all-files
[INFO] Initializing environment for https://github.com/psf/black.
[INFO] Initializing environment for https://github.com/PyCQA/isort.
[INFO] Initializing environment for https://github.com/PyCQA/flake8.
[INFO] Installing environment for https://github.com/psf/black.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/PyCQA/isort.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/PyCQA/flake8.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
black....................................................................Failed
- hook id: black
- files were modified by this hook

reformatted app.py

All done! ✨ ? ✨
1 file reformatted.

isort....................................................................Failed
- hook id: isort
- files were modified by this hook

Fixing /Users/trankien/data/platform/test/app.py

flake8...................................................................Failed
- hook id: flake8
- exit code: 1

app.py:2:1: F401 'os' imported but unused
app.py:11:11: F821 undefined name 'response1'

Một số điều bạn cần lưu ý từ kết quả trên:

  • Pre-commit cần khởi tạo các hook mà bạn khai báo ở file .pre-commit-config.yaml trong lần đầu bạn chạy pre-commit. Việc này có thể sẽ kéo dài vài phút tuỳ vào cấu hình máy của bạn.
  • Thứ tự chạy các hook tương ứng với thứ tự hook mà bạn khai báo ở file .pre-commit-config.yaml. Trong trường hợp này, black sẽ chạy đầu tiên, rồi đến isort và cuối cùng là flake8.
  • black đã phát hiện ra và tự động sửa lỗi về khoảng cách (lỗi số 3).
  • isort đã phát hiện ra và tự động sửa lỗi về thứ tự import (lỗi số 2).
  • flake8 đã phát hiện ra các lỗi còn lại (lỗi số 1 và số 4) với mô tả hết sức chi tiết. Từ các thông tin này, bạn có thể tìm ra vị trí lỗi và sửa lại một cách dễ dàng.

File app.py sau khi chạy pre-commit sẽ có nội dung như sau:

# This is a sample Python script.
import os

import requests

if __name__ == "__main__":
    # the required first parameter of the 'get' method is the 'url':
    response = requests.get("https://w3schools.com/python/demopage.htm")
    abc = "123"
    # print the response text (the content of the requested file):
    print(response1.text)

Như vậy, pre-commit đã phát hiện ra tất cả các lỗi và tự động sửa được lỗi số 2 và số 3.

Lưu ý: Khi chạy pre-commit, nếu bạn thấy thông báo no files to check nghĩa là bạn chưa thêm file app.py vào Git repository. Bạn có thể làm điều đó thông qua lệnh git add <đường dẫn tới file app.py>.

Trên đây là hướng dẫn về việc sử dụng pre-commit để kiểm tra và tự động sửa các lỗi PEP8. Hy vọng qua bài viết này, bạn có thể áp dụng pre-commit vào dự án của mình để tạo ra code Python dễ đọc, dễ hiểu và dễ bảo trì hơn.

Nếu bạn thấy bài viết này hữu ích thì hãy lưu lại và chia sẻ tới bạn bè ngay nhé! Đừng quên theo dõi trang Got It AI Vietnam và ghé thăm chuyên mục Tech Blogs vào tuần cuối cùng của mỗi tháng để khám phá thêm nhiều kiến thức công nghệ thú vị!

Nguồn tham khảo:

Đọc thêm về quy trình tuyển dụng tại đây.

https://d1iv5z3ivlqga1.cloudfront.net/wp-content/uploads/2021/04/29235048/1_QAG9RXQyyMAY7i9OYo84FA.png
Got It Vietnam
May 26, 2023
Share this post to:
Tags:
0 Comments
Inline Feedbacks
View all comments
Các bài viết liên quan
Các bước tạo một thư viện Python

Các bước tạo một thư viện Python

Tác giả: Minh (Software Engineer | CAI) Trong Tech Blog số này, Got It sẽ cùng bạn tìm hiểu về 6 bước để tạo và phân phối một thư viện Python. Cụ thể, chúng ta sẽ viết một CLI command tương tự cowsay cùng với một function để các package khác có thể import và […]
Sử dụng pre-commit để thực thi PEP8 chỉ trong 3 bước

Sử dụng pre-commit để thực thi PEP8 chỉ trong 3 bước

Tác giả: Kiên (Software Engineer | CAI) Đảm bảo code tuân thủ đầy đủ các quy tắc được đề xuất trong PEP8 là một điều vô cùng quan trọng, đặc biệt là trong làm việc nhóm, khi mà yếu tố dễ đọc, dễ hiểu, và dễ bảo trì code được đặt lên hàng đầu. Dẫu […]
Hướng dẫn cách triển khai và debug code Python trên Docker

Hướng dẫn cách triển khai và debug code Python trên Docker

Tác giả: Kiên (Software Engineer | CAI) Bạn đã bao giờ mất hàng tiếng đồng hồ, thậm chí vài ngày để cài đặt một số thư viện cần thiết cho việc chạy một project trên máy tính của mình chưa? Nếu có thì đây là bài viết dành cho bạn. Thông thường, khi bạn tham […]
Readable Code

Readable Code

Tác giả: Minh (Software Engineer, CAI) & Hương (TPM, CAI) Mục lục1. Readable code là gì?2. Làm thế nào để viết code dễ đọc?2.1. Style guide2.2. Viết function nhỏ, tập trung vào một tính năng2.3. Đặt tên hợp lý2.3.1. Dùng các tiền tố thích hợp để phân loại function2.3.2. Hạn chế thêm thông tin về […]
Tìm hiểu Tuple trong Python, phân biệt Tuple và List

Tìm hiểu Tuple trong Python, phân biệt Tuple và List

Ở bài viết này, chúng ta sẽ cùng đi tìm hiểu về Tuple trong Python, cách sử dụng chúng như thế nào, và sự khác biệt giữa Tuple và List là gì? Tất cả những nội dung trong bài đọc sẽ đều có ví dụ minh hoạ cụ thể, hi vọng các bạn đọc có […]
Anaconda là gì? Tìm hiểu nền tảng Khoa học dữ liệu phổ biến nhất

Anaconda là gì? Tìm hiểu nền tảng Khoa học dữ liệu phổ biến nhất

Để có thể tạo nên một ứng dụng của riêng mình, điều quan trọng nhất đó là phải thiết lập môi trường làm việc đúng cách. Vì vậy, bạn cần các công cụ để xử lý dữ liệu, xây dựng các mô hình và biểu diễn trên đồ thị. Việc sử dụng nhiều công cụ […]