Module-module di dalam sebuah package hampir selalu saling membutuhkan: module laporan memakai function dari module teks, submodule layar memanggil utilitas di induknya. Untuk kebutuhan itu Python menyediakan dua gaya penulisan — absolute import yang menuliskan jalur penuh dari package terluar, dan relative import yang memakai titik untuk bergerak relatif terhadap posisi file saat ini. Pada Chapter ini kita memakai keduanya dalam satu package yang sama, memetakan aturan satu-titik dan dua-titik, lalu menetapkan kapan masing-masing layak dipilih.
Studi Kasus: Package aplikasi #
Kita pakai struktur berikut sepanjang Chapter:
belajar/
├── program.py
└── aplikasi/
├── __init__.py
├── teks.py
├── laporan.py
└── layar/
├── __init__.py
└── tampilan.pyModule teks.py berisi satu function util:
def judul_rapi(teks):
return teks.strip().title()Dua module lain, laporan.py dan layar/tampilan.py, sama-sama membutuhkan judul_rapi — tetapi keduanya menulis import dengan gaya berbeda. Isi laporan.py:
from .teks import judul_rapi
def buat_baris(nama):
return f"| {judul_rapi(nama)} |"Isi layar/tampilan.py:
from ..teks import judul_rapi
def tampilkan_judul(nama):
print("=== " + judul_rapi(nama) + " ===")Program utama program.py mengimpor keduanya secara absolute dari luar package:
from aplikasi.laporan import buat_baris
from aplikasi.layar.tampilan import tampilkan_judul
print(buat_baris(" toko maju jaya "))
tampilkan_judul("laporan penjualan")Output yang Dihasilkan:
| Toko Maju Jaya |
=== Laporan Penjualan ===Absolute Import: Jalur Penuh dari Puncak #
Absolute import menuliskan jalur lengkap dari package terluar — from aplikasi.teks import judul_rapi. Kelebihannya ada dua. Pertama, lokasi asal setiap nama terbaca jelas tanpa perlu melihat posisi file yang sedang dibaca. Kedua, bentuk ini tetap bekerja walau kita memindahkan module laporan.py ke subpackage lain, karena jalurnya tidak bergantung pada posisi file pemanggil.
Bentuk ini pula yang dipakai program utama di luar package — program.py berada di luar aplikasi, sehingga satu-satunya cara menjangkaunya adalah lewat jalur penuh dari atas.
Relative Import: Bergerak dari Posisi Sendiri #
Relative import memakai titik untuk bergerak dari lokasi file saat ini:
| Bentuk | Artinya | Contoh posisi pemakai |
|---|---|---|
from . import sesuatu | module/package satu folder dengan file ini | laporan.py mengambil teks |
from .. import sesuatu | naik satu folder package | tampilan.py mengambil isi aplikasi |
from .teks import judul_rapi | module teks satu folder dengan file ini | laporan.py |
from ..teks import judul_rapi | module teks di folder induk | tampilan.py |
Pada studi kasus kita, laporan.py berada satu folder dengan teks.py sehingga cukup satu titik. Sebaliknya tampilan.py hidup di dalam layar/, sedangkan teks.py ada di folder induk aplikasi/ — karena itu dibutuhkan dua titik untuk naik satu tingkat sebelum turun ke teks.
Keunggulan relative import: bila suatu hari seluruh package aplikasi diubah namanya, tidak ada satu pun baris import di dalamnya yang perlu disentuh — titik-titiknya tetap benar.
Jebakan: Relative Import di File yang Dijalankan Langsung #
Relative import hanya berlaku di dalam package. File yang dijalankan langsung dengan python3 tidak punya induk package, sehingga titiknya tidak punya arti. Kita buktikan dengan menjalankan laporan.py langsung:
$ python3 aplikasi/laporan.py
Traceback (most recent call last):
File "/home/budi/belajar/aplikasi/laporan.py", line 1, in <module>
from .teks import judul_rapi
ImportError: attempted relative import with no known parent packageJalur lengkap pada traceback mengikuti komputer tempat perintah dijalankan — isi pesannya sama di mana pun. Kesalahan ini muncul karena python3 aplikasi/laporan.py memperlakukan laporan.py sebagai script lepas, bukan bagian dari package aplikasi.
Kapan Memakai yang Mana #
Pedoman resmi Python (PEP 8) merekomendasikan absolute import sebagai pilihan bawaan, dan mengizinkan relative import bila layout package kompleks hingga absolute import menjadi bertele-tele:
| Situasi | Bentuk yang disarankan |
|---|---|
| Import dari luar package | absolute — from aplikasi.laporan import buat_baris |
| Import antar-module dalam package | absolute bila memungkinkan, misalnya from aplikasi.teks import judul_rapi |
| Package internal yang sangat rapat dan rawan berubah nama | relative — from .teks import judul_rapi |
| File yang dijalankan langsung sebagai script | jangan pakai relative import |
Kata kuncinya eksplisit: gaya apa pun yang dipilih, asal setiap nama jelas asalnya dan tidak mengandalkan kebetulan urutan pencarian. Kode yang eksplisit tetap benar saat struktur berubah; kode yang mengandalkan kebetulan hanya benar sampai kebetulannya berakhir.
Persoalan yang tersisa berbeda nuansanya: bagaimana bila sebuah file memang perlu berperan dua — menjadi program yang bisa dijalankan langsung, sekaligus module yang aman diimpor program lain? Python punya mekanisme khusus untuk itu, dan kuncinya adalah variabel __name__, topik Chapter berikutnya.