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:
- PEP 8 – Style Guide for Python Code
- Kiến thức về Git mà lập trình viên phải biết
- What are Git-hooks & How to use them?
Mục lục
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, isort và flake. 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ỗiundefined 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:
- Unused import ở dòng số 3 (
import os
). Thư việnos
được import vào nhưng không được sử dụng trong fileapp.py
. - 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
. - 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 (=). - 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: