- Dalam alur menempatkan skrip otomatisasi di
~/bin/ lalu menjalankannya, penggunaan uv dan metadata skrip inline memungkinkan skrip Python dikelola dengan lebih ringan
- Jika
~/bin ada di PATH, Anda bisa menetapkan shebang ke #!/usr/bin/env -S uv run --script agar nama file dapat dijalankan seperti perintah
- Pengaturan ini membuat shell lebih dulu menjalankan
uv run --script, lalu meneruskan file skrip saat ini sebagai argumen
- uv mengabaikan baris shebang lalu menjalankan sisa isi file seperti file Python biasa
- Berikan izin eksekusi dengan
chmod a+x {filname} agar dapat digunakan sebagai skrip command-line Python sederhana yang menangani dependensi secara otomatis
Menjalankan uv sebagai shebang
- Untuk otomatisasi pekerjaan, beberapa skrip dibuat dan digunakan di direktori
~/bin/
- Jika
~/bin sudah termasuk dalam PATH, skrip dapat dijalankan langsung hanya dengan nama filenya
- Shebang yang digunakan dalam kasus ini adalah sebagai berikut
#!/usr/bin/env -S uv run --script
Alur eksekusi dan pengaturan izin
- Shebang di atas menjalankan
uv run --script dari command line dan meneruskan file skrip sebagai argumen
- uv mengabaikan shebang lalu menjalankan sisa file sebagai kode Python biasa
- Sebelum dijalankan, skrip harus diberi izin eksekusi
chmod a+x {filname}
- Setelah pengaturan selesai, Anda bisa langsung menjalankan skrip command-line Python sederhana yang menangani dependensi secara otomatis
1 komentar
Komentar Hacker News
Hari ini saya baru tahu tentang env -S, dan begitu melihat shebang di artikel, saya langsung berpikir, “Ini pasti tidak akan jalan di Linux, karena shebang hanya bisa meneruskan satu argumen”
Misalnya, jika menjalankan
foo.pyyang diawali dengan#!/usr/bin/env -S uv run --script, sistem operasi sebenarnya meneruskan seluruh baris shebang sebagai satu argumen, seperti/usr/bin/env '-S uv run --script' foo.pyNamun opsi
-Spadaenvmemecah kembali string itu menjadi beberapa argumen, sehingga bisa berjalan. Sangat keren dan bergunaJika setelah
#!/usr/bin/guile \baris berikutnya berisi-e main -slalu ditutup dengan!#, hasilnya menjadi seperti/usr/bin/guile -e main -s filenameSaya penasaran mengapa mereka memilih cara seperti ini. Mungkin karena
env -Sbaru ditambahkan belakangan, atau tidak tersedia di semua platform yang mereka pedulikanhttps://www.gnu.org/software/guile/manual/html_node/The-Meta-Switch.html
maketetapi menggunakan YAML untuk konfigurasiPasang
#!/usr/bin/env -s go run github.com/rliebz/tusk@latest -fsebagai shebang, lalu gunakan gosh, shell Go, sebagai interpreter sepertiinterpreter: go run mvdan.cc/sh/v3/cmd/gosh@latest -sDengan begitu, selama Go terpasang, ini menjadi CLI yang bisa dijalankan di arsitektur apa pun
Misalnya nix-shell bisa memakai
#!/usr/bin/env nix-shell, lalu pada baris berikutnya menaruh#!nix-shell --pure -i runghc ./default.nixuntuk menentukan dependensi dan argumen, kemudian melanjutkannya dengan kode HaskellAturan pemisahan spasi yang aneh pada baris shebang adalah bug lama yang mengeras menjadi cacat Unix yang tidak bisa diperbaiki
Setiap kali memakai trik seperti di atas, saya terpikir bahwa kalau saja pada 1980-an ada yang meluangkan 30 menit, kejengkelan selama bertahun-tahun setelahnya bisa dihindari. Baris shebang seharusnya sejak awal dipisahkan seperti
/bin/shIni bukan shebang, tetapi belakangan saya memakai uv seperti alat instalasi
Karena sulit memaketkan dan mendistribusikan tool CLI Python yang memiliki dependensi kompleks, saya memanfaatkannya dengan dua cara
Yang pertama adalah menyalin skrip instalasi
curl | shlalu menambahkanuv tool install --python python3.12 my-tooldi bagian akhir agar pengguna bisa memasang CLI dengan satu baris. Yang kedua adalah membuat paket “installer” kecil di PyPI yang hanya bergantung padauv, lalu membuatnya menjalankanuv tool installKedua cara itu memasang tool CLI, Python 3.12, dan semua dependensi Python ke lingkungan terisolasi. Pengguna tidak perlu mengelola virtual environment, dan pada cara
curl | sh, Python bahkan tidak perlu sudah terpasangSetelah itu, jumlah issue GitHub yang muncul karena pengguna merusak dependensi kompleks jauh berkurang
Detail dan tautan kode: https://aider.chat/2025/01/15/uv.html
openssl-dev,gzip,ffi, dan harus mengompilasi PythonSetidaknya saat memakai ASDF-VM, saya pernah mengalami hal seperti itu karena tool instalasi Python lain di dalamnya
misedanaquajuga punya konsep instalasi tool yang bergunaMumpung ada pembahasan menarik soal shebang, saya pernah membuat hal seperti ini untuk menjalankan file Prolog
.pldari shell/*usr/bin/env scryer-prolog "$0" "$@" ; exit #*/Kalau bahasa skrip tidak mendukung komentar
#atau shebang#!secara langsung, tetapi punya komentar/**/, sepertinya ini umumnya akan bekerjaKomentar asli: https://github.com/mthom/scryer-prolog/issues/2170#issuecomment-1821713993
File ini adalah file shell yang valid sekaligus file Prolog yang valid. Saat dijalankan sebagai shell, baris pertama mencari pola glob
/*usr/bin/env, menjalankan/usr/bin/env, laluenvmenjalankanscryer-prolog "test.pl". Di sisi Prolog, baris pertama dianggap komentar/* ... */dan diabaikanSetelah itu shell menjalankan
exitsetelah;agar sisa kode Prolog tidak ditafsirkan sebagai shell, dan#membuat shell mengabaikan*/, penutup komentar Prolog, sehingga mencegah keluaran errorMungkin ini hal terbaik sekaligus terburuk yang pernah saya buat
Selain itu, program C juga bisa dibuat dapat dieksekusi dengan memakai baris pertama berbentuk
//usr/bin/env sh -c .... Saat dijalankan, ia dibuild denganmakelalu menjalankan biner hasilnya, jadi kalau source diubah lalu dijalankan lagi, output yang berubah langsung munculSetelah
#!/bin/sh, bisa menaruh baris# the next line restarts using tcl \lalu membuatnya menjalankanexec tclsh "$0" "$@"Ini memanfaatkan fakta bahwa di TCL baris komentar pun bisa memakai line continuation
Tulisan Trey Hunner, Lazy self-installing Python scripts with uv, punya detail lebih lengkap beserta contoh
https://treyhunner.com/2024/12/lazy-self-installing-python-scripts-with-uv/
printf %.1s 0{1..80} $'\n'ataufor i in {1..80}; do echo -n 0; done; echoUntuk contoh ffmpeg juga saya kurang paham apa bedanya dengan
ffmpeg -i in.mp4 -c:v copy -filter:a volumedetect -pass 1 -f null /dev/null && ffmpeg -i in.mp4 -c:v copy -filter:a "loudnorm" -pass 2 out.mp4Sejujurnya, versi Python terlihat lebih rumit
Untuk pekerjaan kecil, trik ini bisa dipakai bersama mise(mise-en-place): https://mise.jdx.dev/tasks/toml-tasks.html#shell-shebang
Caranya adalah menaruh
uv = 'latest'ditools, lalu di dalam blokrununtuk task mendeklarasikan#!/usr/bin/env -S uv run --scriptdandependencies = ["requests<3", "rich"], kemudian memasukkan kode Python16 hari lalu juga ada artikel dan diskusi terkait: Uv's killer feature is making ad-hoc environments easy https://news.ycombinator.com/item?id=42676432 (502 poin, 417 komentar)
Ini trik yang layak diingat
Belakangan saya mengganti alias Python menjadi
uv run python, dan rasanya cukup nyaman. Tidak perlu mengelola.venvdan semacamnya, tidak perlu memikirkan masalah instalasi sistem atau instalasi global/pengguna, dan ini khususnya membantu di DebianSaat menjalankan REPL di dalam proyek atau environment pun bisa dipanggil tanpa
activate, sehingga hal yang perlu dipikirkan jadi berkurangNamun saat memanggil
.pylangsung dengan uv, kekurangannya adalah path file proyek/environment ditentukan berdasarkan direktori kerja saat ini, bukan berdasarkan lokasi file.pyAda switch eksplisit
--project, jadi bisa dipakai sepertiuv run --project /script.py, tetapi akan lebih bagus kalau ada switch proyek relatif terhadap file target agar pengulangan bisa dikurangiSaat memakai
uvatauuvxsebagai command runner, saya memang menemui beberapa jebakan, tetapi sebagian besar waktu ia bekerja dengan baik, dan saat itu terjadi, ia sangat menghemat waktuSebagai pengembang Python sekaligus orang yang selalu penasaran, direktori home saya dipenuhi shallow clone dan direktori uji coba sekali pakai; sangat berguna karena ini mengurangi beban pengelolaan seperti itu
Saya ingin meniru ide ini. Saya penasaran apakah mereka memakai ekstensi terpisah selain
.py, atau apakah file.pyyang executable bit-nya aktif dan memiliki shebang saja sudah dianggap sebagai sinyal bahwa file itu bisa langsung dijalankan sebagai skrip, bukan dengan Python sistemBukan berarti nol, tetapi saya cukup serius mencarinya. Kalau bisa tahu jebakan apa saja yang pernah Anda alami, saya ingin menambahkannya ke daftar
.pydengan executable bit dan baris shebang yang disebut di artikelDi Pipenv, ada masalah ketika dependensi tertentu memiliki wheel yang berbeda per platform, sementara di Poetry ini berjalan baik
Lock file Pipenv hanya menyertakan dependensi untuk platform tempat locking dilakukan, tetapi Poetry menambahkan semua variasi platform ke lock file
Saya belum menemukan dokumentasi tentang bagaimana uv berperilaku dalam kasus ini
Intinya begini
PEP yang baru-baru ini dipublikasikan mendefinisikan cara skrip Python mendeklarasikan dependensi di komentar awal, dan uv adalah runner skrip Python sekaligus manajer paket yang memindai dependensi tersebut, memenuhinya, lalu menjalankan skrip dalam keadaan modul-modul itu bisa diimpor
Jika pada shebang, yaitu komentar baris pertama skrip Python, file dipanggil dengan
uvalih-alihpython, efek ini otomatis didapat saat “menjalankan” skripHasilnya, skrip Python yang memiliki dependensi yang perlu disiapkan pun bisa langsung dijalankan
$PATHDan meskipun uv akan memasang dependensi, belum jelas apakah dengan cara ini interpreter Python juga otomatis dipasang
Secara pribadi, saya tidak melihat ini menghemat waktu dibanding cara lama membuat environment lalu memanggilnya
Saya juga belum yakin apakah uv bisa memuat environment dalam sesi interaktif, atau hanya dipakai untuk menjalankan skrip
Jika Anda suka TypeScript, cara yang sama juga bisa dipakai dengan Deno. Bun sepertinya juga bisa, tetapi saya belum mencobanya sendiri
Tulis seperti
#! /usr/bin/env -S deno run, dan jika perlu flag izin, tambahkan seperti#! /usr/bin/env -S deno run --allow-env --allow-read --allow-net