Packaging dan distribusi

Menulis pyproject.toml, membangun wheel, dan pengenalan publikasi ke PyPI.

Daftar isi

Kode yang hanya berada di satu komputer tidak mudah dipakai orang lain, sedangkan packaging mengemas proyek menjadi paket terdistribusi yang dapat dipasang dengan satu perintah pip. Topik ini membahas penulisan pyproject.toml sebagai pusat metadata proyek, pembangunan paket menjadi wheel dan sdist, pengujian paket hasil build, serta pengenalan publikasi ke PyPI. Proyek contohnya bernama penghitung-kata, yaitu alat kecil penghitung kata yang dipakai sebagai wadah pembahasan dari awal sampai akhir. Setelah membacanya, proyek sendiri dapat dikemas, dipasang kembali, dan disiapkan untuk dipublikasikan.

pyproject.toml sebagai pusat metadata#

Alat modern Python umumnya membaca konfigurasi proyek dari satu berkas bernama pyproject.toml. Bagian [build-system] menyatakan alat yang dibutuhkan untuk membangun paket beserta backend-nya, sedangkan bagian [project] menyimpan metadata mengikuti standar PEP 621, seperti nama, versi, deskripsi, dan versi Python minimum. Bagian [project.scripts] mendeklarasikan perintah command line yang dibuat otomatis ketika paket dipasang. Berkas berikut adalah konfigurasi lengkap untuk proyek penghitung-kata.

toml pyproject.toml
[build-system]
requires = ["setuptools>=77"]
build-backend = "setuptools.build_meta"

[project]
name = "penghitung-kata"
version = "0.1.0"
description = "Menghitung jumlah kata dan frekuensinya dari sebuah teks."
readme = "README.md"
requires-python = ">=3.12"
license = "MIT"

[project.scripts]
penghitung-kata = "penghitung_kata.cli:utama"

Nilai penghitung_kata.cli:utama pada [project.scripts] berarti perintah penghitung-kata memanggil fungsi utama yang berada di modul penghitung_kata.cli. Metadata yang sama dibaca oleh pip, alat build, dan pemeriksa statis, sehingga nama, versi, dan batas versi Python cukup dinyatakan satu kali. Penambahan dependensi pihak ketiga dilakukan pada bagian [project] melalui kunci dependencies, misalnya dependencies = ["rich>=13"] apabila keluaran program membutuhkan pustaka itu.

Membaca kembali metadata dengan tomllib#

Berkas pyproject.toml berformat TOML, dan sejak Python 3.11 pustaka standar menyediakan modul tomllib untuk membacanya. Pemeriksaan cepat atas isi konfigurasi tidak memerlukan alat tambahan, sebagaimana ditunjukkan contoh berikut yang membaca berkas pyproject.toml pada bagian sebelumnya.

python Contoh: membaca pyproject.toml dengan tomllib
import tomllib

with open("pyproject.toml", "rb") as berkas:
    data = tomllib.load(berkas)

print(data["project"]["name"])
print(data["project"]["version"])
print(data["project"]["scripts"])
text Keluaran
penghitung-kata
0.1.0
{'penghitung-kata': 'penghitung_kata.cli:utama'}

Modul ini dipakai di banyak tempat, termasuk pemeriksa statis yang membaca bagian [tool.mypy] dan linter yang membaca bagian [tool.ruff] pada berkas yang sama. Satu berkas konfigurasi akhirnya melayani seluruh perangkat proyek, sehingga tidak ada metadata yang tersebar di beberapa tempat.

Wheel dan sdist#

Proses build menghasilkan dua bentuk distribusi yang tersimpan di folder dist. Bentuk pertama adalah wheel, yaitu paket jadi yang dapat dipasang pip tanpa proses build lagi. Bentuk kedua adalah sdist (source distribution), yaitu arsip kode sumber yang dibangun ulang di komputer pengguna ketika dipasang. Kedua bentuk dihasilkan bersamaan oleh satu perintah build.

bash
# tidak-dijalankan
# membangun wheel dan sdist dari akar proyek
pip install build
python -m build
text
dist/
├── penghitung_kata-0.1.0-py3-none-any.whl
└── penghitung_kata-0.1.0.tar.gz

Nama wheel tersebut memuat informasi yang terbaca langsung, yaitu nama proyek, versi 0.1.0, penanda py3-none-any yang berarti cocok untuk Python 3 apa pun tanpa bagian khusus platform, dan akhiran .whl. Perbandingan keduanya dirangkum pada tabel berikut.

AspekWheelsdist
Isikode siap pasang beserta metadatanyakode sumber dan konfigurasi build
Saat dipasanglangsung dibongkar pipdibangun lebih dahulu oleh backend
Nama berkasberakhiran .whlberakhiran .tar.gz

Alur lengkap dari kode sumber sampai paket yang terpasang pada lingkungan pengguna dirangkum pada diagram berikut.

kode sumber danpyproject.tomlpython -m buildfolder dist berisiwheel dan sdisttwine uploadPyPIpip installpaket terpasang di lingkungan pengguna
Alur dari kode sumber sampai paket terpasang di lingkungan pengguna

Menguji paket hasil build#

Sebelum dipublikasikan, paket hasil build diuji dengan memasangnya dari folder dist pada lingkungan yang bersih. pip adalah alat pemasang paket yang hadir bersama Python, dan nomor versinya dapat diperiksa sebagai berikut.

bash
# memeriksa versi pip yang terpasang
pip --version
text Keluaran
pip 26.2.2 from /home/kal/.venv/lib/python3.12/site-packages/pip (python 3.12)

Pemasangan dari berkas lokal memakai nama berkas wheel-nya secara langsung, lalu keberadaan paket dapat diverifikasi dengan pip show.

bash
# tidak-dijalankan
# memasang wheel hasil build dari folder dist, lalu memeriksa metadatanya
pip install dist/penghitung_kata-0.1.0-py3-none-any.whl
pip show penghitung-kata

Apabila paket memuat [project.scripts], perintah penghitung-kata tersedia di terminal setelah pemasangan, sehingga perilaku program dapat diuji persis seperti yang akan dialami pengguna yang memasangnya dari internet. Uji semacam ini menangkap kesalahan kemasan yang tidak terlihat dari folder proyek, misalnya modul yang terlewat dari paket.

Publikasi ke PyPI#

PyPI (Python Package Index) adalah repositori publik yang menjadi sumber pip install secara bawaan. Unggahan dilakukan dengan twine, alat yang mengirimkan isi folder dist ke PyPI disertai verifikasi metadata sebelum pengiriman. Akun PyPI dan token API diperlukan untuk autentikasi, dan akun baru wajib mengaktifkan autentikasi dua faktor.

bash
# tidak-dijalankan
# mengunggah seluruh paket di folder dist ke PyPI
pip install twine
twine upload dist/*

Sebelum unggahan ke target resmi, latihan dapat dilakukan pada TestPyPI, salinan PyPI yang dikelola untuk percobaan. Tanda --repository testpypi pada perintah twine upload mengarahkan unggahan ke sana, sehingga kesalahan konfigurasi tidak menyentuh nama proyek yang sesungguhnya.

Kesalahan umum#

Kesalahan pertama adalah mengunggah ulang versi yang sama setelah memperbaiki kode. twine menolaknya dengan pesan bahwa berkas sudah ada, karena nama berkas paket memuat nomor versinya. Perbaikannya adalah menaikkan nomor versi pada pyproject.toml, membangun ulang, lalu mengunggah versi yang baru.

Kesalahan kedua adalah lupa mendeklarasikan dependensi pada kunci dependencies. Program berjalan mulus di komputer pengembang karena pustaka yang dibutuhkan sudah terpasang di sana, tetapi memunculkan ImportError di komputer pengguna. Setiap impor di luar pustaka standar dinyatakan pada metadata, dan pip memasangnya secara otomatis bersama paket.

Kesalahan ketiga adalah mengunggah isi folder dist yang bercampur antara beberapa versi build. Folder yang tidak dibersihkan menyimpan berkas lama, sehingga versi yang salah bisa terkirim. Hapus folder dist sebelum setiap build, atau build ulang sepenuhnya setelah nomor versi diubah.

Ringkasan#

  • pyproject.toml menampung metadata proyek pada bagian [project], konfigurasi alat build pada [build-system], dan perintah CLI pada [project.scripts].
  • Pustaka standar tomllib membaca kembali berkas tersebut, dan alat lain membaca bagiannya masing-masing pada bagian [tool.*].
  • python -m build menghasilkan wheel yang siap dipasang dan sdist yang dibangun ulang di komputer pengguna.
  • Publikasi dilakukan dengan twine ke TestPyPI untuk latihan atau ke PyPI untuk rilis, dan setiap unggahan membutuhkan nomor versi yang belum pernah dipakai.

Referensi#