2 poin oleh GN⁺ 2025-01-29 | 1 komentar | Bagikan ke WhatsApp
  • 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

 
GN⁺ 2025-01-29
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.py yang 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.py
    Namun opsi -S pada env memecah kembali string itu menjadi beberapa argumen, sehingga bisa berjalan. Sangat keren dan berguna

    • Di macOS, perilaku ini tidak sama, jadi cukup menjengkelkan: https://unix.stackexchange.com/a/774145
    • Ini mengingatkan pada cara GNU Guile menangani batas satu argumen dengan shebang multi-baris
      Jika setelah #!/usr/bin/guile \ baris berikutnya berisi -e main -s lalu ditutup dengan !#, hasilnya menjadi seperti /usr/bin/guile -e main -s filename
      Saya penasaran mengapa mereka memilih cara seperti ini. Mungkin karena env -S baru ditambahkan belakangan, atau tidak tersedia di semua platform yang mereka pedulikan
      https://www.gnu.org/software/guile/manual/html_node/The-Meta-Switch.html
    • Cara ini cocok dipakai bersama tusk, CLI Go yang mirip make tetapi menggunakan YAML untuk konfigurasi
      Pasang #!/usr/bin/env -s go run github.com/rliebz/tusk@latest -f sebagai shebang, lalu gunakan gosh, shell Go, sebagai interpreter seperti interpreter: go run mvdan.cc/sh/v3/cmd/gosh@latest -s
      Dengan begitu, selama Go terpasang, ini menjadi CLI yang bisa dijalankan di arsitektur apa pun
    • Jika wrapper-nya mendukung, baris-baris berikutnya juga bisa memuat lebih banyak informasi
      Misalnya nix-shell bisa memakai #!/usr/bin/env nix-shell, lalu pada baris berikutnya menaruh #!nix-shell --pure -i runghc ./default.nix untuk menentukan dependensi dan argumen, kemudian melanjutkannya dengan kode Haskell
    • env -S seharusnya tidak perlu ada sejak awal
      Aturan 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/sh
  • Ini 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 | sh lalu menambahkan uv tool install --python python3.12 my-tool di bagian akhir agar pengguna bisa memasang CLI dengan satu baris. Yang kedua adalah membuat paket “installer” kecil di PyPI yang hanya bergantung pada uv, lalu membuatnya menjalankan uv tool install
    Kedua 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 terpasang
    Setelah 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

    • Saya belum memeriksa bagaimana cara kerjanya di dalam, tetapi jika sampai memasang tool CLI dan Python 3.12, sepertinya sistem pengguna akhir membutuhkan compiler, header kernel, header library seperti openssl-dev, gzip, ffi, dan harus mengompilasi Python
      Setidaknya saat memakai ASDF-VM, saya pernah mengalami hal seperti itu karena tool instalasi Python lain di dalamnya
    • Bagus. Sepertinya mise dan aqua juga punya konsep instalasi tool yang berguna
  • Mumpung ada pembahasan menarik soal shebang, saya pernah membuat hal seperti ini untuk menjalankan file Prolog .pl dari 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 bekerja
    Komentar 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, lalu env menjalankan scryer-prolog "test.pl". Di sisi Prolog, baris pertama dianggap komentar /* ... */ dan diabaikan
    Setelah itu shell menjalankan exit setelah ; agar sisa kode Prolog tidak ditafsirkan sebagai shell, dan # membuat shell mengabaikan */, penutup komentar Prolog, sehingga mencegah keluaran error
    Mungkin ini hal terbaik sekaligus terburuk yang pernah saya buat

    • Ada juga cara serupa untuk membuat source Go bisa dieksekusi: https://unix.stackexchange.com/questions/162531/shebang-starting-with
      Selain itu, program C juga bisa dibuat dapat dieksekusi dengan memakai baris pertama berbentuk //usr/bin/env sh -c .... Saat dijalankan, ia dibuild dengan make lalu menjalankan biner hasilnya, jadi kalau source diubah lalu dijalankan lagi, output yang berubah langsung muncul
    • Ini bukan ide saya sendiri, tetapi TCL juga memakai pola seperti ini
      Setelah #!/bin/sh, bisa menaruh baris # the next line restarts using tcl \ lalu membuatnya menjalankan exec tclsh "$0" "$@"
      Ini memanfaatkan fakta bahwa di TCL baris komentar pun bisa memakai line continuation
    • Ini benar-benar luar biasa. Kalau redirect input/output Scryer sedikit diperbaiki, rasanya akan sempurna sebagai pengganti bash script
  • 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/

    • Di antara contohnya, “skrip yang mencetak 80 angka 0” juga bisa dilakukan di shell dengan printf %.1s 0{1..80} $'\n' atau for i in {1..80}; do echo -n 0; done; echo
      Untuk 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.mp4
      Sejujurnya, 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' di tools, lalu di dalam blok run untuk task mendeklarasikan #!/usr/bin/env -S uv run --script dan dependencies = ["requests<3", "rich"], kemudian memasukkan kode Python

  • 16 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 .venv dan semacamnya, tidak perlu memikirkan masalah instalasi sistem atau instalasi global/pengguna, dan ini khususnya membantu di Debian
    Saat menjalankan REPL di dalam proyek atau environment pun bisa dipanggil tanpa activate, sehingga hal yang perlu dipikirkan jadi berkurang
    Namun saat memanggil .py langsung dengan uv, kekurangannya adalah path file proyek/environment ditentukan berdasarkan direktori kerja saat ini, bukan berdasarkan lokasi file .py
    Ada switch eksplisit --project, jadi bisa dipakai seperti uv run --project /script.py, tetapi akan lebih bagus kalau ada switch proyek relatif terhadap file target agar pengulangan bisa dikurangi

  • Saat memakai uv atau uvx sebagai command runner, saya memang menemui beberapa jebakan, tetapi sebagian besar waktu ia bekerja dengan baik, dan saat itu terjadi, ia sangat menghemat waktu
    Sebagai 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 .py yang executable bit-nya aktif dan memiliki shebang saja sudah dianggap sebagai sinyal bahwa file itu bisa langsung dijalankan sebagai skrip, bukan dengan Python sistem

    • Selama setahun terakhir saya memakai uv sendiri untuk melihat apakah layak direkomendasikan, sambil mengumpulkan daftar jebakan, dan ternyata jumlahnya tidak terlalu banyak
      Bukan berarti nol, tetapi saya cukup serius mencarinya. Kalau bisa tahu jebakan apa saja yang pernah Anda alami, saya ingin menambahkannya ke daftar
    • Sejauh yang saya pahami, caranya adalah memakai .py dengan executable bit dan baris shebang yang disebut di artikel
    • Saya benar-benar penasaran jebakan apa yang muncul
      Di 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 uv alih-alih python, efek ini otomatis didapat saat “menjalankan” skrip
    Hasilnya, skrip Python yang memiliki dependensi yang perlu disiapkan pun bisa langsung dijalankan

    • Namun, uv harus terpasang di $PATH
      Dan meskipun uv akan memasang dependensi, belum jelas apakah dengan cara ini interpreter Python juga otomatis dipasang
    • Pada akhirnya, baru setelah memasang uv di sistem dan menambahkan baris dependensi di depan semua skrip, semuanya menjadi “langsung jalan”
      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