- Bahkan skrip kecil untuk menguji API pun perlu menyesuaikan lingkungan eksekusi karena dependensi, tetapi dengan shebang eksekusi uv skrip bisa dibuat agar langsung dapat dijalankan tanpa prosedur instalasi
- Contoh
jam_users.py menguji endpoint /users pada API Go dengan httpx, IPython, dan loguru, lalu menghapus dan membuat pengguna sebelum masuk ke REPL
- Cara lama mengharuskan paket dipasang secara global pada Python sistem atau menyiapkan virtual environment secara manual, sehingga berbagi dan menjalankan ulang skrip menjadi merepotkan
- Jika mendeklarasikan
dependencies = ["ipython", "httpx", "loguru"] pada header # /// script lalu menjalankan uv run jam_users.py, uv akan menangani lingkungan terisolasi dan instalasi dependensi
- Dengan menambahkan shebang
#!/usr/bin/env -S uv run --script dan izin eksekusi, pada sistem Unix skrip bisa dijalankan seperti ./jam_users.py dengan syarat hanya uv yang sudah terpasang
Mendeklarasikan dependensi di dalam skrip
- Contoh
jam_users.py menyiapkan data pengguna uji untuk API lokal http://localhost:4000/v1/users
- Mengirim permintaan API dengan httpx
- Masuk ke REPL IPython untuk memeriksa respons dan melanjutkan pengujian
- Mencatat log penghapusan dan pembuatan dengan
loguru
- Alur skrip dasarnya adalah menginisialisasi ulang daftar pengguna lalu mengisi kembali data uji
- Mengambil daftar pengguna yang ada dengan
GET /v1/users
- Memanggil
DELETE /v1/users/{id} untuk setiap pengguna
- Mengirim daftar pengguna yang sudah disiapkan sebagai JSON ke
POST /v1/users
- Setelah itu menjalankan
IPython.embed() untuk membuka REPL
- Untuk menjalankannya dengan
python jam_users.py, httpx, IPython, dan loguru harus sudah terpasang di lingkungan eksekusi
- Memasang secara global pada Python sistem atau membuat virtual environment terpisah memang bisa, tetapi keduanya tetap memerlukan persiapan sebelum dijalankan
- Instalasi global bisa membuat Python sistem penuh dengan paket
- Pendekatan virtual environment mengharuskan proses pembuatan, aktivasi, instalasi, dan eksekusi dikelola secara manual
- Keduanya juga memerlukan Python sistem yang kompatibel dengan paket yang dibutuhkan
Membuat skrip yang bisa langsung dijalankan dengan uv
- Dengan menambahkan tag
# /// script milik uv di bagian atas skrip, dependensi dapat dideklarasikan langsung di dalam file
# /// script
# dependencies = ["ipython", "httpx", "loguru"]
# ///
- Jika header ini ada, skrip bisa dijalankan dengan
uv run jam_users.py
- uv membuat virtual environment terisolasi untuk skrip tersebut
- Mengunduh dan memasang dependensi yang dibutuhkan
- Menjalankan skrip dalam konteks virtual environment itu
- Shebang Python biasa
#!/usr/bin/env python tidak bisa memanfaatkan header skrip uv karena Python mengabaikan komentar # /// script
- Jika pemanggilan uv dimasukkan langsung ke shebang, skrip dapat diperlakukan seperti berkas eksekusi
#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["ipython", "httpx", "loguru"]
# ///
- Flag
-S pada env membuat string setelahnya dipecah menjadi argumen terpisah lalu diteruskan ke env
- Setelah memberi izin eksekusi dengan
chmod +x jam_users.py, skrip bisa dijalankan langsung seperti berikut
./jam_users.py
- Pendekatan ini memungkinkan skrip dijalankan tanpa instalasi dependensi terpisah atau pengelolaan virtual environment, selama uv terpasang pada sistem Unix
- Saat membagikan skrip Python yang lebih kompleks kepada pengguna lain, beban untuk menjelaskan langkah persiapan sistem sebelum eksekusi bisa jauh berkurang
1 komentar
Pendapat di Hacker News
Bukan soal UV itu sendiri, tetapi secara umum, cara mengendalikan eksekusi kode dengan komentar terasa mengganggu
Memakai komentar untuk instruksi linter atau catatan developer tidak masalah, tetapi kalau itu data terkait konfigurasi atau eksekusi, menurut saya bentuk seperti
UV_ENV = { "dependencies": { "requests": "2.32.3", "pandas": "2.2.3" } }jauh lebih baikCara ini adalah sintaks Python yang valid, lebih mudah dibuat dan divalidasi karena memakai struktur data standar alih-alih parsing komentar secara arbitrer, dan yang terpenting, tetap memegang prinsip bahwa meski semua komentar dihapus, kode harus berjalan dengan cara yang sama
Cara yang diusulkan itu pun pada runtime tidak melakukan apa-apa, yaitu konstanta ajaib, sehingga hanya diparsing lewat analisis statis; alat lain bisa saja menganggapnya kode tak terpakai dan menghapusnya, bukannya dibaca oleh uv
Lebih baik setelah
import uv, panggil langsung apa yang harus dilakukan uv, misalnyauv.exec(dependencies=["clown"], python=">=3.10")Eksekusi pertama dilakukan di runtime Python mana pun yang bisa menemukan paket
uvhipotetis ini, lalu setelah paketuvmenyiapkan virtual environment dan runtime Python, ia melakukanre-exec(3)dengan flag seperti variabel lingkunganPada runtime kedua,
uv.execyang mendeteksi flag itu cukup tidak melakukan apa-apahttps://peps.python.org/pep-0723/
Selain itu, baris shebang sendiri sebenarnya juga berfungsi sebagai komentar
Hanya saja selama 45 tahun ia sudah begitu mengakar sehingga orang jarang menyadari bahwa itu adalah komentar shell
Jika dependensi yang sama sudah diinstal, kode akan berjalan dengan cara yang sama
Ini bukan mengubah makna kode itu sendiri, melainkan mengubah lingkungan tempat kode dijalankan, dan dalam hal itu tidak berbeda dari komentar
#!/bin/bashdi awal skrip shellNamun uv kemungkinan besar tidak ingin menjalankan kode hanya untuk mengetahui dependensi, jadi ini harus berupa subset sintaks Python yang sangat terbatas
Fakta bahwa hal seperti ini dibutuhkan sejak awal menunjukkan kelemahan bahasa tersebut
Pernyataan
importsendiri seharusnya bisa menyampaikan semua informasi tentang dependensiDalam beberapa bulan terakhir topik ini sangat sering muncul di HN, dan contoh terbarunya adalah sebagai berikut
https://news.ycombinator.com/item?id=43500124
https://news.ycombinator.com/item?id=42463975
Saya suka uv, tetapi sulit menyetujui istilah self-contained karena dua hal
Pertama, untuk menjalankan skrip, uv harus sudah terinstal
Memang bisa membuat skrip shell yang memeriksa apakah uv sudah terinstal dan jika belum menginstalnya lewat curlpipe, tetapi boilerplate-nya akan cukup bertambah dan pendekatan curlpipe itu sendiri juga kurang baik
Kedua, membuat virtual environment secara otomatis di suatu tempat di direktori home bukanlah self-contained yang sebenarnya
Meski dijalankan sekali lalu skripnya dihapus, virtual environment itu tetap tersisa dan memakan ruang; saya tidak menemukan jaminan di dokumentasi uv bahwa virtual environment sementara seperti ini akan dibersihkan otomatis
curl | sh, memang validNamun, begitu package manager mulai memasukkan uv ke repositori mereka, ini akan makin kurang menjadi masalah
Misalnya uv sudah tersedia di Alpine Linux dan Homebrew: https://repology.org/project/uv/versions
Selain itu, metadata skrip inline adalah standar Python
Jika sistem tidak memiliki uv dan uv juga belum dipaketkan, tetapi ada versi Python yang cocok untuk skrip, skrip bisa dijalankan dengan pipx: https://pipx.pypa.io/stable/examples/#pipx-run-examples
pipx jauh lebih luas dipaketkan: https://repology.org/project/pipx/versions
Di mesin developer acak, Docker mungkin lebih umum daripada uv, dan karena artikel aslinya juga menyebut proyek perusahaan, ini terasa masuk akal
Namun saat ini sama sekali belum ada caching, jadi setiap kali dijalankan akan mengunduh lagi, yang terasa canggung; sepertinya bisa diperbaiki dengan volume
Kira-kira seperti ini: https://hugojosefson.github.io/docker-shebang/#python
Meski begitu, jika saat eksekusi ia mengunduh sesuatu yang tidak jelas dari internet, sulit menyebutnya self-contained; self-contained yang benar-benar lengkap lebih dekat ke AppImage
Dengan memakai sesuatu seperti py2exe, kita bisa membuat “skrip Python” yang self-contained
Bagi developer, itu menimbulkan banyak masalah, tetapi bagi pengguna masalahnya diminimalkan
Nix juga menggunakan cara yang sama, dan baris shebang-nya terlihat seperti ini
#! nix-shell -i python3 -p "python312.withPackages (pkgs: [ pkgs.boto3 pkgs.click ])"Dengan begitu, satu-satunya yang diperlukan di sistem hanyalah Nix; Python bahkan tidak perlu terpasang
Contoh yang paling obvious adalah bash dengan semua dependensi ditentukan, dan saya juga pernah membuat skrip Rust satu file yang cepat dengan Nix shebang
https://nixos.wiki/wiki/Nix-shell_shebang
nix shell, alih-alihnix-shellSeperti komentar-komentar lain, klaim “self-contained” bergantung pada fakta bahwa
uvsudah terpasangJika benar-benar menginginkan skrip Python yang self-contained, kompiler Nuitka layak dilihat
Saya memakainya di produksi untuk layanan gRPC tanpa masalah, dan cukup menjalankan
nuitka --onefile run.pyKarena ini kompiler, binary yang dihasilkan juga bisa lebih cepat daripada program Python asli yang dibundel dengan PyInstaller
Di halaman GitHub pembuatnya tertulis, “misi hidup saya adalah terus mencoba membuat Python Compiler terbaik yang mungkin sampai saya tua dan mati”
https://nuitka.net/
https://github.com/kayhayen
Saya sangat menyukai pola ini, tetapi sayangnya belum berhasil membuatnya bekerja dengan benar bersama LSP
Saya memakai pyright di Helix, dan tetap tidak berhasil meski menjalankan editor dengan
uv run hx script.pyBisa saja melakukan sesuatu seperti
uv run --with whatever-it-is-i-need hx script.py, tetapi duplikasinya makin banyakuvebuatan sendiri yang jelek$ cat ~/.local/bin/uve#!/bin/bashtemp=$(mktemp)uv export --script $1 --no-hashes > $tempuv run --with-requirements $temp vim $1unlink $tempSaya berharap editor segera mendukung
uv python find --scriptKelihatannya cukup berguna
Saya penasaran apakah uv adalah pilihan yang lebih aman untuk distribusi jangka panjang proyek berbasis Python
Saya teringat rug pull ketika sekitar 5 tahun lalu memakai Anaconda untuk manajemen dependensi, lalu belakangan aturannya berubah sehingga pelanggan organisasi dengan lebih dari 200 karyawan tidak lagi bisa memakai Anaconda secara gratis dan harus membayar lisensi komersial
Mereka bisa menghentikan pengembangan atau memindahkan pekerjaan berikutnya ke fork dengan lisensi lain, tetapi tidak bisa mengubah lisensi masa lalu secara retroaktif, jadi yang sudah ada saat ini dijamin open source
Jika benar-benar khawatir, buat saja fork dan terus sinkronkan
Pada dasarnya ini juga berlaku hampir sama untuk proyek OSS lain, jadi saya tidak akan terlalu khawatir
Sejauh yang saya tahu, conda tidak pernah menjadi open source dan selama ini mendistribusikan binary
https://github.com/astral-sh/uv?tab=readme-ov-file#license
Paket-paket conda-forge masih bisa dipakai gratis
uv hanya menggunakan PyPI, jadi jika ada masalah, tinggal beralih dari uv ke pip atau Poetry dan paketnya tetap diambil dari tempat yang sama
Pemilik seperti itu pada akhirnya akan diakuisisi oleh orang kaya terburuk yang bisa dibayangkan
Saya sempat menelusuri panduan kontribusi dan issue uv tetapi tidak melihat CLA, sedangkan PyTorch memiliki CLA di bagian paling atas panduan kontribusinya
Meski begitu, seharusnya ada fork komunitas dari versi FOSS terakhir Anaconda
Itu terjadi pada Redis, dan Redis juga menggunakan CLA: https://github.com/redis/redis/blob/unstable/CONTRIBUTING.md#redis-software-grant-and-contributor-license-agreement
Jangan pernah menandatangani CLA
Saya lebih memilih hanya berkontribusi pada proyek copyleft
Kita dibayar terlalu mahal untuk bekerja secara gratis
Untuk utilitas kecil, ini terlihat seperti alternatif packaging yang bagus dibanding containerization
Sekarang saya harus meyakinkan semua rekan kerja untuk memasang uv
Ini terlihat mirip dengan bundler/inline di Ruby
Senang melihat hal serupa hadir di Python, dan dalam praktiknya memang sangat nyaman
https://bundler.io/guides/bundler_in_a_single_file_ruby_script.html
Penasaran apakah ada yang berhasil membuat ini berjalan di Windows
Saya ingin memakai trik ini untuk tool bagi mod game yang sedang saya kerjakan, tetapi tidak berhasil membuat trik shebang-nya berjalan
$> uv init --script .py$> uv add --script .py ...$> uv add --script .py --dev ...$> uv run .pySemoga membantu
Sumber: https://docs.astral.sh/uv/guides/scripts/
.pypy launcher mendukung baris shebang
Ini juga dibahas dalam posting blog bertopik sama yang naik beberapa hari lalu, dan menurut posting itu
-Sharus dihilangkan: https://thisdavej.com/share-python-scripts-like-a-pro-uv-and-pep-723-for-easy-deployment/https://news.ycombinator.com/item?id=43500124
Saya belum mencobanya sendiri; sebagai gantinya saya mengubah file association agar semua file
.pysecara default dibuka denganuv runhttps://docs.python.org/3/using/windows.html#python-launcher-for-windows
https://peps.python.org/pep-0397/
https://pyinstaller.org
https://onor.io/2025/01/more-scripting-with-racket.html
Use case ini membuat saya menyukai uv, tetapi rasanya bertentangan dengan Zen of Python bahwa PEP yang resmi dan sangat berguna tidak didukung oleh tool Python resmi
Dari sudut pandang saya, ini adalah momen pertama ketika Python tidak lagi “batteries included”
Sekarang saya juga punya dua dependency manager Python di sistem
Saya tahu ada banyak hal yang bisa dikatakan soal manajemen dependency Python, tetapi selama beberapa tahun terakhir saya bertahan dengan
pip+venvbawaan selama proyek hanya punyarequirements.txtSeingat saya,
pyproject.tomlmuncul lebih dulu daripada librarytomllibJadi selama beberapa versi, kita harus mendefinisikan modul dalam bahasa yang tidak bisa dibaca Python secara bawaan
Ini situasi yang lebih buruk daripada memiliki cara bawaan untuk menyertakan metadata yang tidak digunakan
Toh itu memang metadata, dan kalau tidak, seharusnya itu sekadar sintaks Python