Kursus Python / Membuat paket wheel dan memverifikasi instalasi bersih

Proyek Python dapat mendeklarasikan metadata dan konfigurasi build dalam pyproject.toml, kemudian menghasilkan file distribusi seperti wheel. Untuk memastikan paket benar-benar dapat dipakai, pasang wheel pada lingkungan bersih dan jalankan pemeriksaan di luar folder sumber. Cara itu mengungkap impor yang hanya berhasil karena file proyek kebetulan berada pada jalur pencarian.

Membedakan nama distribusi, paket impor, dan alat build

Nama distribusi latihan ini adalah expensekit-demo, sedangkan paket yang diimpor bernama expensekit. Nama distribusi boleh memakai tanda hubung dan tidak harus sama dengan nama modul Python. expense-total adalah nama perintah konsol yang nantinya dipasang untuk memanggil fungsi main pada modul CLI.

Struktur src menempatkan kode yang akan diimpor di bawah folder terpisah. Ini membantu mencegah root proyek menyembunyikan kesalahan pemasangan. Pengujian instalasi tetap diperlukan; keberadaan folder src saja belum membuktikan wheel berisi semua file.

Gunakan Python 3.12 atau lebih baru dan lingkungan virtual pengembangan. Nama proyek berikut dipakai untuk latihan lokal, bukan pernyataan bahwa nama publik tersedia atau dimiliki Anda. Pada latihan ini, distribusi dibangun dan dipasang secara lokal. Pengunggahan paket ke PyPI merupakan pekerjaan terpisah dari menerbitkan artikel ini.

Membuat semua file proyek

Buat folder project baru dengan subfolder src/expensekit. Simpan fungsi lengkap berikut sebagai src/expensekit/__init__.py dengan UTF-8:

def total(amounts):
    if any(type(x) is not int or x < 0 for x in amounts):
        raise ValueError("invalid amount")
    return sum(amounts)

Simpan modul berikut sebagai src/expensekit/cli.py:

import argparse
from . import total

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("amounts", type=int, nargs="+")
    args = parser.parse_args()
    print(total(args.amounts))

if __name__ == "__main__":
    main()

Buat pyproject.toml pada root project dengan seluruh isi berikut:

[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"

[project]
name = "expensekit-demo"
version = "0.1.0"
description = "Local expense sum example"
requires-python = ">=3.12"

[project.scripts]
expense-total = "expensekit.cli:main"

[tool.setuptools.packages.find]
where = ["src"]

Bagian build-system memilih backend setuptools. Metadata project menyatakan nama, versi, dan batas minimum Python. project.scripts menghubungkan nama perintah konsol dengan fungsi main, sementara pengaturan pencarian paket menunjuk src. Proyek contoh tidak memakai dependensi runtime pihak ketiga; alat build bukan otomatis dependensi yang dibutuhkan pengguna paket.

Fungsi total memvalidasi list bilangan bulat nonnegatif lalu menjumlahkannya. Kontrak latihan ini adalah koleksi yang dapat dilintasi kembali, bukan generator sekali pakai: any melakukan lintasan validasi sebelum sum. Main guard pada modul CLI memastikan impor tidak langsung memulai pembacaan argumen. Dasarnya tersedia pada paket dan pintu masuk program.

Membangun dan memasang wheel pada lingkungan bersih

Dari folder yang berisi pyproject.toml, gunakan interpreter lingkungan pengembangan untuk memasang frontend build dan menjalankan pembangunan:

python -m pip install build
python -m build

Build dapat mengunduh kebutuhan backend ke lingkungan build terisolasi, sehingga memerlukan sumber paket yang dapat diakses. Setelah berhasil, folder dist berisi wheel dan distribusi sumber. Jika build gagal, baca pesan backend dan konfigurasi paket; jangan melanjutkan dengan file distribusi lama seolah-olah hasil terbaru.

Buat lingkungan pemeriksaan yang belum berisi expensekit. Pada contoh ini, foldernya berada di root proyek, tetapi tidak di dalam src:

python -m venv .venv-check

Pada Windows PowerShell, gunakan interpreter lingkungan baru untuk memasang wheel lokal:

.\.venv-check\Scripts\python.exe -m pip install dist/expensekit_demo-0.1.0-py3-none-any.whl

Pada macOS atau Ubuntu, gunakan jalur interpreter lingkungan yang sesuai:

.venv-check/bin/python -m pip install dist/expensekit_demo-0.1.0-py3-none-any.whl

Instalasi yang diperiksa harus berasal dari wheel yang baru dibangun, bukan instalasi editable yang masih menunjuk kode sumber. Gunakan jalur lengkap interpreter atau aktifkan lingkungan .venv-check secara benar. Setelah instalasi, pindah ke folder baru di luar project dan jalankan:

python -c "from expensekit import total; print(total([3500,8000,2500]))"
python -m expensekit.cli 3500 8000 2500

Kedua perintah menghasilkan 14000. Jika Anda belum mengaktifkan lingkungan pemeriksaan, ganti python pada setiap baris dengan jalur lengkap interpreter .venv-check; jalur relatif dari folder lama tidak otomatis tetap benar setelah pindah folder. Perintah konsol expense-total 3500 8000 2500 pada lingkungan yang sama harus memanggil main yang sama dan memberi hasil identik.

Sebelum instalasi, impor dari folder luar seharusnya belum menemukan expensekit pada lingkungan baru. Sesudah instalasi, periksa lokasi expensekit.__file__ agar mengarah ke site-packages lingkungan pemeriksaan, bukan folder src. Perbandingan ini membantu mendeteksi pengujian yang tanpa sengaja memakai instalasi pengembangan lama.

Memeriksa isi distribusi, kegagalan, dan kebutuhan rilis

Struktur setelah build berhasil adalah:

project/
  pyproject.toml
  src/
    expensekit/
      __init__.py
      cli.py
  dist/
    expensekit_demo-0.1.0-py3-none-any.whl
    expensekit_demo-0.1.0.tar.gz

Wheel harus menyertakan expensekit/__init__.py, expensekit/cli.py, metadata versi 0.1.0, batas Python, serta entry point konsol. Distribusi sumber harus berisi pyproject.toml dan kedua file sumber. Periksa bahwa rahasia, lingkungan virtual, cache, atau file pekerjaan pribadi tidak ikut dimasukkan. Rincian alur tersedia dalam panduan packaging Python.

Jika impor hanya berhasil dari proyek, periksa interpreter yang dipilih, konfigurasi pencarian paket, isi wheel, dan instalasi yang sebenarnya digunakan. Jangan menambahkan src ke PYTHONPATH hanya untuk membuat pemeriksaan instalasi lolos, karena itu dapat menyembunyikan file yang tidak masuk wheel. Penjelasan src layout dan flat layout membantu membedakan kedua situasi.

  1. Jalankan impor, modul CLI, dan alias konsol dari folder luar, lalu cocokkan hasil 14000.
  2. Ubah satu masukan dari 8000 menjadi 9000 dan pastikan hasil menjadi 15000. Kembalikan ke 8000 dan periksa 14000 lagi.
  3. Coba teks bukan angka dan argumen kosong: parser harus menolak. Nilai negatif lolos konversi int tetapi ditolak oleh total dengan ValueError; contoh CLI belum mengubah error domain itu menjadi pesan argparse yang lebih ramah.
  4. Impor expensekit.cli tanpa argumen dan pastikan hanya impor terjadi. Fungsi main tidak boleh berjalan karena impor saja.

Jika paket memiliki dependensi runtime tambahan, deklarasikan pada project.dependencies dan uji di lingkungan bersih dengan rentang versi Python yang dinyatakan. Pengujian lokal pada satu interpreter tidak membuktikan semua versi dan sistem operasi kompatibel. Build ulang setelah mengubah kode atau metadata dan pasang artefak yang benar pada lingkungan uji baru.

Rilis publik memerlukan pemeriksaan nama, lisensi, informasi penulis yang benar, README, file yang disertakan, autentikasi repositori, dan kebijakan versi. Jangan mengunggah otomatis hanya karena build dan instalasi lokal berhasil. Pertahankan artefak serta hasil pemeriksaan agar versi yang diuji dapat dihubungkan dengan file yang akan dibagikan.