File __init__.py sering ditulis kosong dan tampak seperti formalitas tanpa makna. Kenyataannya, file inilah pintu depan package: isinya dijalankan setiap kali package diimpor, dan dari sinilah kita bisa merancang wajah publik package — menentukan nama apa saja yang layak dipakai pengguna. Pada Chapter ini kita isi __init__.py dengan berbagai tingkat kerumitan, dari yang kosong sampai yang membentuk API rapi dengan from ... import dan __all__.
Apa yang Berjalan Saat Package Diimpor #
Statement import toko menjalankan file toko/__init__.py — persis seperti import sapa menjalankan sapa.py. Karena itu, semua kode tingkat atas di dalam __init__.py dieksekusi pada saat import package. Kita buktikan dengan package sensor:
belajar/
├── program.py
└── sensor/
├── __init__.py
└── suhu.pyIsi sensor/__init__.py — dua statement, bukan kosong:
print("Package sensor diimpor")
from . import suhuIsi sensor/suhu.py:
def baca_suhu(celsius):
return f"Suhu terbaca: {celsius} derajat Celsius"Program utama program.py:
import sensor
print(sensor.suhu.baca_suhu(28))Output yang Dihasilkan:
Package sensor diimpor
Suhu terbaca: 28 derajat CelsiusMari kita bedah kejadiannya:
- Baris 1 (
import sensor): interpreter menjalankansensor/__init__.py— kalimat pembukanya tercetak, lalu statementfrom . import suhumemuat modulesuhudi dalam package yang sama dan menempelkannya sebagai attribute package. - Baris 3 (
sensor.suhu.baca_suhu(28)): berkatfrom . import suhu, pengguna package tidak perlu menulisimport sensor.suhusendiri — submodule sudah tersedia begitu package diimpor. Inilah obat untukAttributeError: module 'toko' has no attribute 'produk'yang kita temui pada Chapter Package dan Subpackage.
init.py Kosong Itu Wajar #
Berdasarkan contoh di atas, sepertinya __init__.py wajib berisi sesuatu. Tidak demikian: file kosong adalah isi yang paling umum dan sepenuhnya sah. Package yang isinya sekadar kumpulan module — seperti package toko kita sebelumnya — tidak butuh apa pun di pintu depannya. Kehadiran file kosong tersebut tetap penting untuk menandai folder sebagai package biasa (regular package) dan memudahkan alat bantu pengembangan menemukannya.
Membentuk API Publik Package #
from ... import di __init__.py tidak hanya bisa memuat submodule — file tersebut juga bisa mengangkat function tertentu langsung ke level package. Bayangkan pengguna package harus menulis sensor.suhu.baca_suhu(31) setiap kali; dengan mengganti isi sensor/__init__.py menjadi satu baris, jalur itu dipendekkan:
from .suhu import baca_suhuSekarang baca_suhu adalah nama di level package. Program pengguna menjadi jauh lebih ramping:
from sensor import baca_suhu
print(baca_suhu(31))Output yang Dihasilkan:
Suhu terbaca: 31 derajat CelsiusKeselarasan bentuk import di kedua sisi — from .suhu import baca_suhu di dalam package dan from sensor import baca_suhu di luar — membuat penulisan package terasa simetris. Prinsip desainnya: pengguna cukup tahu apa yang bisa dipakai, tanpa perlu tahu di file mana function itu didefinisikan. Kita bebas merapikan isi internal tanpa memecah kode pengguna.
all Menyaring Nama Publik #
Daftar nama __all__ menentukan nama apa saja yang diekspor bila pengguna menulis from module import *. Karena star import tetap mengambil semua nama publik secara bawaan, __all__ berperan sebagai daftar tamu resmi. Contoh module utilitas.py:
__all__ = ["format_rupiah"]
def format_rupiah(angka):
return f"Rp{angka:,}".replace(",", ".")
def _catatan_internal():
return "hanya untuk di dalam module"
def bantu_lainnya():
return "tidak masuk daftar __all__"Program pengguna melakukan star import:
from utilitas import *
print(format_rupiah(1250000))
print(bantu_lainnya())Output yang Dihasilkan:
Rp1.250.000
Traceback (most recent call last):
File "/home/budi/belajar/belanja.py", line 4, in <module>
print(bantu_lainnya())
^^^^^^^^^^^^^
NameError: name 'bantu_lainnya' is not definedTraceback lengkap menampilkan jalur file sesuai komputer tempat program dijalankan — pesan intinya sama di mana pun. Dua hal terjadi di sini:
format_rupiahberhasil dipakai karena namanya tercantum di dalam list__all__.bantu_lainnyamenimbulkanNameErrormeskipun didefinisikan publik — star import hanya mengambil nama di__all__bila daftar itu ada.
Sedangkan nama _catatan_internal tidak ikut dalam kedua kasus: tanpa __all__, star import memang sudah melewati semua nama yang diawali garis bawah, sehingga awalan _ menjadi konvensi penanda “urusan dalam negeri” module.
Sampai di sini, semua import di dalam package kita memakai bentuk relative — from . import suhu. Chapter berikutnya membedah dua gaya import tersebut secara berdampingan: absolute dan relative, beserta aturan kapan masing-masing layak dipilih.