Nội dung chính
- 1 Tại sao cần học module & package?
- 2 Module là gì?
- 3 Cách import: absolute vs relative, from … import …
- 4 Package là gì?
- 5 Ví dụ thực tế: tạo một package “calculator”
- 6 if __name__ == "__main__": — module vừa là module vừa là script
- 7 Quản lý môi trường: venv / virtualenv
- 8 pip cơ bản (cài, nâng cấp, gỡ)
- 9 requirements.txt
- 10 Tạo package chuẩn: pyproject.toml (khuyến nghị hiện nay)
- 11 Cài package đang phát triển (editable install)
- 12 Entry points / tạo CLI cho package
- 13 Testing cơ bản: pytest
- 14 Relative imports và vấn đề khi chạy module trực tiếp
- 15 Namespace packages (PEP 420)
- 16 Lazy imports (nhập khi cần) và performance
- 17 Circular imports (vòng lặp import) và cách tránh
- 18 Best practices & style khi làm module/package
- 19 Ví dụ nâng cao: kết hợp mọi thứ vào project nhỏ
- 20 Khi nào tạo module riêng, khi nào dùng thư viện có sẵn?
- 21 Tóm tắt — checklist khi làm module/package
- 22 Bài tập thực hành (có lời hướng dẫn)
- 23 Tầm quan trọng của module & package
Tại sao cần học module & package?
Khi chương trình lớn lên (100 → 1.000 → 10.000 dòng), bạn không thể giữ mọi thứ trong một file .py duy nhất. Module và package là cách Python cho phép bạn tổ chức, tái sử dụng, phân phối và chia sẻ mã nguồn. Hiểu rõ module/package giúp bạn:
-
Viết code có cấu trúc, dễ bảo trì.
-
Dùng lại code giữa nhiều project.
-
Cài đặt thư viện bên thứ ba (via
pip). -
Tạo package để phát hành cho cộng đồng (PyPI).
-
Quản lý môi trường (venv) để tránh xung đột dependency.

Bài này sẽ hướng dẫn từ cơ bản → thực tế: cách tạo module, package, import, virtualenv/venv, pip, requirements.txt, packaging (pyproject.toml), entry points, testing cơ bản, và best practices.
Module là gì?
-
Module = một file Python (ví dụ
utils.py,math_utils.py) chứa biến, hàm, class… -
Bạn có thể
importmodule để dùng các thành phần bên trong.
Ví dụ math_utils.py:
Dùng module:
Diễn giải: import math_utils nạp module và bạn truy cập tên bằng math_utils.<name>.
Cách import: absolute vs relative, from … import …
Absolute import
From-import (chỉ lấy tên cần thiết)
Lưu ý: from module import * hiếm khi nên dùng — gây ô nhiễm namespace.
Relative import (trong package)
Trong package, bạn có thể dùng . và ..:
Trong subpkg/b.py, import a.py bằng:
Diễn giải: relative import chỉ dùng trong package (khi bạn chạy toàn bộ package, hoặc cài package; chạy file module trực tiếp có thể gây lỗi import tương đối).
Package là gì?
-
Package = thư mục chứa file
__init__.py(trước kia bắt buộc; giờ có namespace packages nhưng dùng__init__.pyvẫn phổ biến), chứa nhiều module và subpackage. -
Cho phép tổ chức module theo cấu trúc.
Ví dụ cấu trúc package:
__init__.py có thể để trống hoặc export các API mặc định:
Diễn giải: khi import mypkg, Python thực thi mypkg/__init__.py. Dùng __all__ để kiểm soát from mypkg import *.
Ví dụ thực tế: tạo một package “calculator”
Cấu trúc:
operations.py:
__init__.py:
Sử dụng:
if __name__ == "__main__": — module vừa là module vừa là script
Trong file module, bạn có thể thêm đoạn này để cho phép chạy file trực tiếp:
-
Khi
python file.py→__name__ == "__main__"→ chạymain(). -
Khi
import file→__name__ == "file"→ không chạy.
Diễn giải: hữu ích để test module đơn giản.
Quản lý môi trường: venv / virtualenv
Vì các project dùng các version package khác nhau, luôn tạo môi trường ảo (virtual environment).
-
Tạo venv (Python 3 built-in):
-
Kích hoạt:
-
Windows:
.\venv\Scripts\activate -
macOS/Linux:
source venv/bin/activate
-
-
Cài package (sau activate):
-
Lưu dependencies:
-
Cài dependencies từ file:
Diễn giải: venv giúp cô lập dependencies giữa project.
pip cơ bản (cài, nâng cấp, gỡ)
-
Cài package:
pip install <package> -
Cài phiên bản cụ thể:
pip install requests==2.31.0 -
Nâng cấp:
pip install --upgrade <package> -
Gỡ:
pip uninstall <package>
Lưu ý: cài trong venv để tránh cài global.
requirements.txt
File văn bản liệt kê dependencies, ví dụ:
Sử dụng pip freeze > requirements.txt để tạo file từ môi trường hiện tại. Khi deploy hoặc share project, dùng pip install -r requirements.txt.
Tạo package chuẩn: pyproject.toml (khuyến nghị hiện nay)
pyproject.toml là chuẩn hiện đại để mô tả package, thay thế setup.py/setup.cfg truyền thống.
Ví dụ tối giản:
-
Sau khi cấu hình, bạn có thể build:
(tạo dist/ chứa wheel và sdist).
-
Upload lên PyPI với
twine(ngoài phạm vi chi tiết từng bước).
Diễn giải: pyproject là tiêu chuẩn PEP 518/PEP 621; hiện là cách hiện đại để packaging.
Cài package đang phát triển (editable install)
Khi phát triển package, dùng:
Trong thư mục chứa pyproject.toml hay setup.py. -e (editable) cho phép thay đổi mã nguồn ngay lập tức có hiệu lực trong môi trường.
Diễn giải: tiện lợi khi code package và test trong project khác.
Entry points / tạo CLI cho package
Bạn có thể tạo command-line entry point để người dùng chạy lệnh từ terminal.
Trong pyproject.toml (setuptools) hoặc setup.cfg, cấu hình entry_points:
Nếu build & cài, người dùng có thể gõ calc để chạy calculator/cli.py‘s main().
Ví dụ calculator/cli.py:
Testing cơ bản: pytest
Viết test giúp bảo vệ code khi refactor.
Cài pytest: pip install pytest
Ví dụ test cho operations.py:
test_operations.py:
Chạy pytest để chạy tất cả test. Tích hợp CI (GitHub Actions) là bước tiếp theo.
Diễn giải: test giúp tránh regressions.
Relative imports và vấn đề khi chạy module trực tiếp
-
Khi dùng relative import, không chạy file module trực tiếp (
python subpkg/module.py), vì__package__sẽ khác và imports tương đối phá vỡ. -
Thay vào đó, chạy package bằng:
-m chạy module theo package context, import tương đối sẽ hoạt động.
Namespace packages (PEP 420)
Bạn có thể tạo package không cần __init__.py — gọi là namespace package. Thường dùng khi nhiều project muốn đóng gói subpackages chung. Tuy nhiên cho người mới, tốt nhất vẫn dùng __init__.py.
Lazy imports (nhập khi cần) và performance
Đôi khi import sẽ tốn thời gian (nạp nhiều module). Nếu một hàm chỉ dùng một package lớn vài trường hợp, bạn có thể import bên trong hàm:
Diễn giải: tránh chi phí import khi module được import ở những tình huống không dùng chức năng đó.
Circular imports (vòng lặp import) và cách tránh
Circular import xảy ra khi a.py import b.py và b.py import a.py. Triệu chứng: AttributeError hoặc ImportError vì module chưa được khởi tạo.
Cách tránh:
-
Tái cấu trúc: tách phần chung ra module thứ ba (
common.py). -
Dùng import trong hàm (lazy import).
-
Dùng interfaces/abstractions để giảm phụ thuộc.
Ví dụ fix:
Fix bằng tách shared.py.
Best practices & style khi làm module/package
-
Đặt tên package, module ngắn, có ý nghĩa, không đặt tên trùng stdlib (ví dụ
json.py). -
Tách logic thành module theo trách nhiệm (SRP).
-
Sử dụng
__all__nếu muốn giới hạn export. -
Không dùng wildcard import (
from X import *). -
Document (docstring) module & hàm.
-
Viết tests.
-
Sử dụng semantic versioning (MAJOR.MINOR.PATCH).
-
Để
requirements.txtvàpyproject.tomlrõ ràng. -
Dùng CI để test & lint (flake8, black).
Ví dụ nâng cao: kết hợp mọi thứ vào project nhỏ
Project: notes – package cho phép lưu/đọc ghi chú text, có CLI.
Cấu trúc:
storage.py:
cli.py:
Trong pyproject.toml thêm entry point:
Sau build & cài, người dùng chạy notes save mynote --content "hello" rồi notes read mynote.
Khi nào tạo module riêng, khi nào dùng thư viện có sẵn?
-
Nếu chức năng nhỏ & dự án nội bộ → tạo module trong repo.
-
Nếu là chức năng chung, cần dùng nhiều project → cân nhắc làm package và publish lên PyPI.
-
Nếu có thư viện nổi tiếng (requests, numpy, pandas) hãy dùng thay vì reinvent wheel.
Tóm tắt — checklist khi làm module/package
-
Tạo thư mục package với
__init__.py. -
Viết module có docstring, hàm/class rõ ràng.
-
Dùng virtualenv để phát triển.
-
Quản lý dependencies bằng
pyproject.toml/requirements.txt. -
Viết tests (
pytest). -
Dùng
pip install -e .khi phát triển. -
Tạo
pyproject.tomlhợp lệ để build package. -
Thiết lập entry points nếu muốn CLI.
-
Lưu version hợp lý (semantic versioning).
-
Liên tục test & lint trước khi publish.
Bài tập thực hành (có lời hướng dẫn)
-
Tạo module
string_utils.pychứa hàm:-
is_palindrome(s) -
count_vowels(s) -
reverse_words(s)
Viết file test bằng pytest.
-
-
Tạo package
todo:-
todo/storage.pylưu todo vào file JSON. -
todo/cli.pycó lệnhadd,list,remove. -
Tạo
pyproject.tomlvà càipip install -e ., chạy CLI.
-
-
Quản lý dependencies:
-
Tạo venv, cài
requests, exportrequirements.txt. -
Trong một module, lazy-import
requestschỉ khi hàmfetch(url)được gọi.
-
-
Packaging nhỏ:
-
Viết
pyproject.tomlcho packagestring_utils, build wheel, cài wheel vào venv khác.
-
Tầm quan trọng của module & package
Module và package là kỹ năng không thể thiếu để trở thành lập trình viên Python thực thụ. Học cách tổ chức mã nguồn, quản lý môi trường, sử dụng pip và packaging sẽ giúp bạn:
-
Phát triển dự án an toàn, reproducible.
-
Chia sẻ code cho cộng đồng (hoặc team).
-
Dễ dàng liên kết với hệ sinh thái Python rộng lớn.
Tiếp tục chuỗi series tự học python: (BÀI 8): Deployment & CI/CD với GitHub Actions


1 Trackback / Pingback