Saat jumlah module bertambah, menumpuk seluruh file .py dalam satu folder membuat proyek kembali sulit dinavigasi: file laporan bercampur dengan file pembayaran, dan nama mulai bertabrakan. Python menjawabnya dengan package — folder yang mengelompokkan module — dan subpackage — package di dalam package. Pada Chapter ini kita membangun package bertingkat untuk sebuah toko daring, mempelajari peran file __init__.py, dan memakai nama bertitik seperti toko.produk.katalog untuk menjangkau isinya.
Package adalah Folder Berisi Module #
Sebuah folder menjadi package Python bila di dalamnya ada file khusus bernama __init__.py. File tersebut boleh kosong — perannya baru dibedah tuntas pada Chapter init.py. Untuk sekarang, kehadirannya saja sudah cukup untuk menandai “folder ini adalah package”.
Kita bangun struktur proyek toko berikut:
belajar/
├── kasir.py
└── toko/
├── __init__.py
├── produk/
│ ├── __init__.py
│ └── katalog.py
└── pembayaran/
├── __init__.py
└── metode.pyPackage utama toko berisi dua subpackage: produk dan pembayaran — masing-masing adalah package sendiri karena foldernya berisi __init__.py. Isi katalog.py:
PRODUK = {
"P001": ("Kopi Arabika", 85000),
"P002": ("Teh Melati", 45000),
}
def cari_produk(kode):
nama, harga = PRODUK[kode]
return f"{nama} - Rp{harga}"Isi metode.py:
def cek_bayar(total, dibayar):
if dibayar >= total:
kembalian = dibayar - total
return f"Lunas, kembalian Rp{kembalian}"
return "Kurang bayar"Dari luar package, semua diakses dengan nama bertitik — folder menjadi bagian dari nama:
import toko.produk.katalog
from toko.pembayaran.metode import cek_bayar
print(toko.produk.katalog.cari_produk("P001"))
print(cek_bayar(85000, 100000))Output yang Dihasilkan:
Kopi Arabika - Rp85000
Lunas, kembalian Rp15000Mari kita bedah kasir.py baris per baris:
- Baris 1 (
import toko.produk.katalog): interpreter mencaritoko, laluprodukdi dalamnya, lalukatalog— tiga tingkat nama yang dipisahkan titik dan dijalankan berurutan dari yang paling luar. - Baris 2 (
from toko.pembayaran.metode import cek_bayar): bentukfrommenelusuri jalur package yang sama, tetapi hanya mengikat namacek_bayarlangsung di program kita. - Baris 4 (
toko.produk.katalog.cari_produk("P001")): function diambil dari modulekatalogdi dalam subpackageprodukdengan menuliskan seluruh jalurnya.
Perbedaan Module dan Package #
| Aspek | Module | Package |
|---|---|---|
| Wujud | satu file .py | folder berisi __init__.py |
| Nama Python | nama file | nama folder |
| Contoh | katalog | toko.produk |
| Isi | function, konstanta, class | module dan subpackage |
| Cara mengimpor | import katalog | import toko.produk |
Baris pemisah keduanya memang tipis — package secara teknis juga module — tetapi bagi pembaca kode, kata “module” berarti satu file dan “package” berarti folder. Standard library sendiri memakai keduanya: math adalah module tunggal, sedangkan json yang sering kita pakai sebenarnya package berisi beberapa file.
Satu detail penting dari struktur di atas: setiap tingkat folder yang berperan sebagai package membutuhkan __init__.py-nya sendiri — toko/, toko/produk/, dan toko/pembayaran/ masing-masing punya satu. Kedalaman bertingkat seperti toko.produk.katalog membantu pengelompokan, tetapi jangan berlebihan: setiap tingkat menambah satu segmen pada setiap import yang menuliskannya. Aturan praktisnya, pecah folder menjadi subpackage hanya ketika jumlah file di dalamnya sudah membuat navigasi sulit — untuk lima module, satu package datar biasanya masih lebih nyaman dibaca.
Mengimpor Package Tidak Serta-merta Memuat Isinya #
Jebakan klasik: import toko tidak otomatis memuat toko.produk.katalog. Import sebuah package hanya menjalankan __init__.py-nya — tidak menyentuh module di dalamnya. Akibatnya kode berikut gagal:
import toko
print(toko.produk.katalog.PRODUK["P002"])Output yang Dihasilkan:
Traceback (most recent call last):
File "/home/budi/belajar/kasir2.py", line 3, in <module>
print(toko.produk.katalog.PRODUK["P002"])
^^^^^^^^^^^
AttributeError: module 'toko' has no attribute 'produk'Statement import toko membuat nama toko tersedia, tetapi attribute produk belum pernah dimuat ke dalamnya. Aturannya: module yang ingin dipakai harus diimpor eksplisit — import toko.produk.katalog — atau dimuat otomatis lewat __init__.py (trik yang dibahas pada Chapter berikutnya tentang init.py).
Dengan package dan subpackage, proyek kita kini punya struktur. Pertanyaan berikutnya: apa sebenarnya yang boleh dan sebaiknya dituliskan di dalam file __init__.py itu? Chapter berikutnya menjawabnya sekaligus menunjukkan cara merapikan wajah publik sebuah package.