Michael Kennedy vừa ra mắt gilguard (6/11/2026) — package Python nhỏ gọn, không phụ thuộc, phát hiện ngay import nào âm thầm bật lại GIL trên Python free-threaded 3.13t, 3.14t và 3.15t. Chỉ cần đặt import gilguard lên đầu, mọi import sau đó khiến GIL bật lại sẽ ném ra lỗi GILEnabledError, chỉ rõ module thủ phạm.
Python free-threaded — nhiều luồng chạy song song thật sự — đã được hỗ trợ chính thức từ Python 3.14. Nhưng có một “chế độ hỏng” lặng lẽ: một extension C chưa khai báo hỗ trợ free-threading có thể bật lại GIL ngay lúc khởi động, và ứng dụng vẫn chạy bình thường — các luồng lại xếp hàng chờ nhau như cũ.
Vì sao GIL có thể bật lại mà bạn không hay biết
Mỗi extension C phải khai báo rằng nó an toàn khi chạy không có GIL (slot Py_mod_gil). Khi trình thông dịch nạp một extension chưa khai báo, nó bật lại GIL cho cả tiến trình và chỉ để lại một dòng RuntimeWarning trong log khởi động — rất dễ bị bỏ qua. Một khi GIL đã bật lại, không có cách nào tắt nó đi trong suốt vòng đời của tiến trình đó.
gilguard hoạt động như thế nào
Cách dùng rất đơn giản: đặt import gilguard lên đầu, trước mọi import khác — không cần gọi hàm hay cấu hình gì thêm. Khi một import kéo theo extension chưa hỗ trợ free-threading, gilguard ném ra GILEnabledError với đầy đủ thông tin: tên module, package chứa nó, chuỗi import dẫn tới thủ phạm và dòng code của bạn.
Đáng chú ý: GILEnabledError kế thừa từ BaseException, không phải Exception — nếu ném Exception thường, khối except thử import bản tăng tốc của nhiều package sẽ “nuốt” mất lỗi. Chưa muốn dừng ngay thì đặt GILGUARD_ACTION=warn để chỉ nhận cảnh báo, hoặc =off để tắt hẳn.
Quét toàn bộ môi trường và đưa vào CI
Một tiến trình chỉ phát hiện được module đầu tiên bật lại GIL — sau đó GIL đã bật rồi. Vì vậy gilguard kèm công cụ quét: chạy python -m gilguard để kiểm tra mọi package đã cài, mỗi package chạy trong một trình thông dịch riêng. Lệnh thoát với mã 1 khi tìm thấy thủ phạm nên gắn thẳng vào CI, có thêm cờ –json. Còn extension chỉ nạp lười khi dùng tính năng lần đầu, hãy chạy test suite với pytest -p gilguard — plugin được nạp trước cả conftest.py.
Điều này có ý nghĩa gì với bạn
Nếu bạn đang hoặc sắp thử Python free-threaded cho Django, FastAPI hay service dùng thread pool, gilguard là bước kiểm tra rẻ nhất trước khi đo hiệu năng: nó trả lời câu hỏi “mình có thật sự đang chạy không GIL không”. Lưu ý: chạy sạch không có nghĩa code an toàn với đa luồng, cũng không đảm bảo thêm luồng là nhanh hơn.
Bài viết liên quan
- Python 3.15.0 chính thức ra mắt: lazy import, JIT nhanh hơn và UTF-8 mặc định — có nên nâng cấp ngay?
- Python 3.16 alpha 1 ra mắt: JIT có thể bị “đá” khỏi CPython — câu chuyện lớn nhất của chu kỳ mới
Câu hỏi thường gặp
gilguard có làm code của tôi chạy nhanh hơn không?
Không — gilguard chỉ phát hiện import nào bật lại GIL, không tối ưu code hay sửa lỗi đa luồng. Nó giúp bạn biết chắc mình đang chạy free-threaded thật trước khi đo hiệu năng.
Tôi có cần dùng Python free-threaded mới dùng được gilguard không?
Đúng, gilguard chỉ có ý nghĩa trên bản free-threaded 3.13t, 3.14t hoặc 3.15t. Trên bản Python thường, GIL luôn bật sẵn — đặt GILGUARD_ACTION=off để cùng một codebase chạy ở cả hai môi trường.
Đặt import gilguard ở đâu trong code?
Ở dòng import đầu tiên của entry point, trước mọi import khác. Nếu một package được import trước, GIL đã bật lại rồi và gilguard không còn gì để bắt nữa.
💬 Tin này ảnh hưởng tới dự án của bạn thế nào? Chia sẻ góc nhìn của bạn trong phần bình luận — mình đọc hết và sẽ tổng hợp những ý hay nhất.
Nguồn tham khảo
- Michael Kennedy, “Catch the import. Name the culprit. Keep threads free: Introducing gilguard”, mkennedy.codes, 6/11/2026 — https://mkennedy.codes/posts/catch-the-import-name-the-culprit-keep-threads-free-introducing-gilguard/
- Django News, Issue 363, 13/11/2026 — https://django-news.com/archive/issue-363-wagtails-new-api/
