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:

text
belajar/
├── program.py
└── aplikasi/
    ├── __init__.py
    ├── teks.py
    ├── laporan.py
    └── layar/
        ├── __init__.py
        └── tampilan.py

Module teks.py berisi satu function util:

python
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:

python
from .teks import judul_rapi

def buat_baris(nama):
    return f"| {judul_rapi(nama)} |"

Isi layar/tampilan.py:

python
from ..teks import judul_rapi

def tampilkan_judul(nama):
    print("=== " + judul_rapi(nama) + " ===")

Program utama program.py mengimpor keduanya secara absolute dari luar package:

python
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:

text
| 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:

BentukArtinyaContoh posisi pemakai
from . import sesuatumodule/package satu folder dengan file inilaporan.py mengambil teks
from .. import sesuatunaik satu folder packagetampilan.py mengambil isi aplikasi
from .teks import judul_rapimodule teks satu folder dengan file inilaporan.py
from ..teks import judul_rapimodule teks di folder induktampilan.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:

bash
$ 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 package

Jalur 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:

SituasiBentuk yang disarankan
Import dari luar packageabsolute — from aplikasi.laporan import buat_baris
Import antar-module dalam packageabsolute bila memungkinkan, misalnya from aplikasi.teks import judul_rapi
Package internal yang sangat rapat dan rawan berubah namarelative — from .teks import judul_rapi
File yang dijalankan langsung sebagai scriptjangan 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.