2 पॉइंट द्वारा GN⁺ 2025-01-29 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • ~/bin/ में automation scripts रखकर चलाने वाले workflow में uv और inline script metadata का उपयोग करने से Python scripts को अधिक हल्के तरीके से संभाला जा सकता है
  • अगर ~/bin PATH में शामिल है, तो shebang को #!/usr/bin/env -S uv run --script पर सेट करके फ़ाइल नाम को कमांड की तरह चलाया जा सकता है
  • यह सेटिंग shell को पहले uv run --script चलाने और फिर मौजूदा script फ़ाइल को argument के रूप में पास करने देती है
  • uv shebang लाइन को अनदेखा करने के बाद बाकी सामग्री को एक सामान्य Python file की तरह चलाता है
  • chmod a+x {filname} से execute permission देने पर इसे dependencies को अपने-आप संभालने वाली एक सरल Python command-line script की तरह इस्तेमाल किया जा सकता है

shebang के रूप में uv चलाना

  • काम के automation के लिए ~/bin/ directory में कई scripts बनाकर उपयोग किया जाता है
  • अगर ~/bin PATH में शामिल है, तो script को सिर्फ़ फ़ाइल नाम से सीधे चलाया जा सकता है
  • इस स्थिति में उपयोग करने वाला shebang इस प्रकार है
#!/usr/bin/env -S uv run --script

execution flow और permission सेटिंग

  • ऊपर दिया गया shebang command line पर uv run --script चलाता है और script फ़ाइल को argument के रूप में देता है
  • uv shebang को अनदेखा करने के बाद फ़ाइल के बाकी हिस्से को सामान्य Python code की तरह चलाता है
  • चलाने से पहले script को execute permission देनी होती है
chmod a+x {filname}
  • सेटिंग पूरी होने के बाद dependencies को अपने-आप संभालने वाली एक सरल Python command-line script को तुरंत चलाया जा सकता है

1 टिप्पणियां

 
GN⁺ 2025-01-29
Hacker News की राय
  • आज पहली बार env -S के बारे में पता चला, और लेख में shebang देखते ही सोचा, “Linux पर तो यह नहीं चलेगा, क्योंकि shebang सिर्फ एक argument पास कर सकता है”
    उदाहरण के लिए, अगर #!/usr/bin/env -S uv run --script से शुरू होने वाला foo.py चलाएँ, तो ऑपरेटिंग सिस्टम असल में पूरी shebang लाइन को एक argument की तरह /usr/bin/env '-S uv run --script' foo.py के रूप में पास करता है
    लेकिन env का -S उस string को फिर से कई arguments में तोड़ देता है, इसलिए यह काम करता है। बहुत बढ़िया और उपयोगी है

    • macOS पर यह व्यवहार वैसा नहीं है, इसलिए झुंझलाहट होती है: https://unix.stackexchange.com/a/774145
    • GNU Guile का एक-argument वाली सीमा को multi-line shebang से संभालने का तरीका याद आता है
      #!/usr/bin/guile \ के बाद अगली लाइन में -e main -s रखें और !# से बंद करें, तो यह /usr/bin/guile -e main -s filename जैसा हो जाता है
      जिज्ञासा है कि उन्होंने खास तौर पर ऐसा क्यों किया। शायद env -S हाल में जोड़ा गया था, या उन सभी platforms पर उपलब्ध नहीं था जिनकी उन्हें परवाह थी
      https://www.gnu.org/software/guile/manual/html_node/The-Meta-Switch.html
    • tusk के साथ यह तरीका इस्तेमाल करना अच्छा है, जो make जैसा Go CLI है लेकिन config के लिए YAML इस्तेमाल करता है
      shebang में #!/usr/bin/env -s go run github.com/rliebz/tusk@latest -f रखें, और interpreter के लिए interpreter: go run mvdan.cc/sh/v3/cmd/gosh@latest -s जैसा Go shell, यानी gosh, इस्तेमाल करें
      ऐसा करने पर सिर्फ Go इंस्टॉल हो तो किसी भी architecture पर चल सकने वाला CLI बन जाता है
    • अगर wrapper सहयोग करे तो बाद की लाइन में और जानकारी भी डाली जा सकती है
      उदाहरण के लिए nix-shell में #!/usr/bin/env nix-shell के बाद अगली लाइन में #!nix-shell --pure -i runghc ./default.nix रखकर dependencies और arguments specify किए जा सकते हैं, और उसके बाद Haskell code लिखा जा सकता है
    • env -S की शुरुआत से ही जरूरत नहीं पड़नी चाहिए थी
      shebang लाइन के अजीब whitespace-splitting नियम एक पुराना bug हैं, जो Unix की ऐसी खामी बन गए जिन्हें अब ठीक नहीं किया जा सकता
      ऊपर जैसी तरकीबें हर बार इस्तेमाल करते हुए लगता है कि 1980 के दशक में सिर्फ 30 मिनट दे दिए होते तो बाद के कई सालों की झुंझलाहट से बचा जा सकता था। shebang लाइन को शुरू से ही /bin/sh की तरह split होना चाहिए था
  • shebang तो नहीं, लेकिन हाल में uv को installation tool की तरह इस्तेमाल कर रहा हूँ
    जटिल dependencies वाले Python CLI tools को package और distribute करना मुश्किल था, इसलिए इसे दो तरीकों से इस्तेमाल किया
    पहला तरीका यह था कि curl | sh install script को copy करके अंत में uv tool install --python python3.12 my-tool जोड़ दिया, ताकि user एक लाइन में CLI install कर सके; दूसरा तरीका यह था कि एक छोटा PyPI “installer” package बनाया, जिसकी केवल dependency uv थी, और उससे uv tool install चलवाया
    दोनों तरीकों में CLI tool, Python 3.12 और सभी Python dependencies एक isolated environment में install होती हैं। users को virtual environment manage करने की जरूरत नहीं होती, और curl | sh तरीके में Python install होना भी जरूरी नहीं है
    उसके बाद users द्वारा जटिल dependencies बिगाड़ देने से बनने वाले GitHub issues काफी कम हो गए
    ज्यादा जानकारी और code links: https://aider.chat/2025/01/15/uv.html

    • अंदर कैसे काम करता है, यह मैंने नहीं देखा, लेकिन अगर CLI tool और Python 3.12 installation तक करता है, तो लगता है end-user system पर compiler, kernel headers, openssl-dev, gzip, ffi जैसी library headers चाहिए होंगी और Python compile करना पड़ेगा
      कम से कम ASDF-VM इस्तेमाल करते समय अंदर के दूसरे Python installation tool की वजह से मेरा ऐसा अनुभव रहा था
    • अच्छा है। लगता है mise और aqua में भी उपयोगी tool installation की अवधारणा है
  • दिलचस्प shebang चर्चा निकली ही है, तो मैंने Prolog .pl फ़ाइल को shell में चलाने के लिए ऐसा कुछ बनाया था
    /*usr/bin/env scryer-prolog "$0" "$@" ; exit #*/
    जिन scripting languages में /**/ comment होता है, लेकिन # comment या #! shebang का direct support नहीं होता, उनमें यह आम तौर पर काम कर सकता है
    मूल comment: https://github.com/mthom/scryer-prolog/issues/2170#issuecomment-1821713993
    यह फ़ाइल valid shell file भी है और साथ ही valid Prolog file भी। shell से चलाने पर पहली line glob pattern /*usr/bin/env खोजती है और /usr/bin/env चलाती है, और env scryer-prolog "test.pl" चलाता है। Prolog की तरफ पहली line /* ... */ comment होने के कारण ignore हो जाती है
    उसके बाद shell ; के बाद वाला exit चलाता है ताकि बाकी Prolog code को shell की तरह interpret न करे, और # shell को Prolog comment terminator */ ignore करवाता है, जिससे error output रुक जाता है
    यह शायद मेरी बनाई हुई चीज़ों में सबसे अच्छी और सबसे खराब दोनों हो सकती है

    • इसी तरह Go source को executable बनाने का तरीका भी है: https://unix.stackexchange.com/questions/162531/shebang-starting-with
      इसके अलावा C programs को भी //usr/bin/env sh -c ... form की पहली line का उपयोग करके executable बनाया जा सकता है। चलते समय यह make से build करके result binary चलाता है, इसलिए source modify करके फिर चलाने पर बदला हुआ output तुरंत दिखता है
    • मैंने खुद नहीं सोचा था, लेकिन TCL में भी ऐसा pattern इस्तेमाल होता है
      #!/bin/sh के बाद वाली line में # the next line restarts using tcl \ रखकर exec tclsh "$0" "$@" चलवाया जा सकता है
      यह इस बात का उपयोग करता है कि TCL में comment lines भी line continuation कर सकती हैं
    • यह सच में कमाल है। Scryer की input/output redirection को थोड़ा ठीक कर दें तो यह bash script का replacement बनने के लिए perfect लगेगा
  • Trey Hunner के Lazy self-installing Python scripts with uv article में examples के साथ ज्यादा detail है
    https://treyhunner.com/2024/12/lazy-self-installing-python-scripts-with-uv/

    • examples में “80 zero print करने वाली script” shell में भी printf %.1s 0{1..80} $'\n' या for i in {1..80}; do echo -n 0; done; echo से संभव है
      ffmpeg example भी 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 से कैसे अलग है, यह मुझे ठीक से समझ नहीं आ रहा
      ईमानदारी से कहूं तो Python वाला तरीका ज्यादा complex दिखता है
  • छोटी tasks के लिए mise(mise-en-place) के साथ यह trick इस्तेमाल की जा सकती है: https://mise.jdx.dev/tasks/toml-tasks.html#shell-shebang
    तरीका यह है कि tools में uv = 'latest' रखें, task के run block में #!/usr/bin/env -S uv run --script और dependencies = ["requests<3", "rich"] declare करें, फिर Python code डालें

  • 16 दिन पहले भी related article और discussion था: Uv's killer feature is making ad-hoc environments easy https://news.ycombinator.com/item?id=42676432 (502 points, 417 comments)

  • याद रखने लायक trick है
    हाल ही में मैंने Python alias को uv run python में बदल दिया है और यह काफ़ी comfortable है। .venv आदि manage करने की जरूरत नहीं रहती, system install या global/user install वाली समस्याओं की चिंता भी नहीं करनी पड़ती, और Debian में यह खास तौर पर मददगार है
    project या environment के अंदर REPL चलाते समय भी activate किए बिना call किया जा सकता है, इसलिए सोचने वाली चीज़ें कम हो जाती हैं
    हालांकि .py को uv से directly call करते समय project/environment file path current working directory के आधार पर तय होता है, .py file की location के आधार पर नहीं—यह एक drawback है
    explicit switch --project है, इसलिए uv run --project /script.py जैसा इस्तेमाल किया जा सकता है, लेकिन अगर target file के आधार पर relative project switch हो तो repetition कम हो सकती है और अच्छा रहेगा

  • uv या uvx को command runner की तरह इस्तेमाल करते हुए कुछ pitfalls तो झेलने पड़े, लेकिन ज़्यादातर समय यह अच्छी तरह काम करता है और तब काफी समय बचा देता है
    Python developer और जिज्ञासु व्यक्ति होने के नाते मेरे home directory में shallow clones और one-off test directories बिखरी रहती हैं, इसलिए यह management burden कम करता है—यह बात सच में उपयोगी है
    यह idea मैं अपनाना चाहूँगा। उत्सुकता है कि क्या आप .py के बजाय कोई अलग extension इस्तेमाल करते हैं, या फिर .py file में execute bit on होना और shebang होना ही यह संकेत मानते हैं कि इसे system Python से नहीं, बल्कि script की तरह सीधे execute किया जा सकता है

    • पिछले 1 साल से uv को recommend किया जा सकता है या नहीं, यह देखने के लिए मैं खुद इस्तेमाल करते हुए pitfalls की list जमा कर रहा हूँ, और हैरानी की बात है कि वे बहुत ज़्यादा नहीं निकले
      शून्य तो नहीं हैं, लेकिन मैं काफी ध्यान से ढूँढ रहा हूँ। आपने कौन-से pitfalls झेले, यह पता चले तो मैं उन्हें list में जोड़ना चाहूँगा
    • मेरी समझ के मुताबिक तरीका यह है कि .py पर execute bit और article में दी गई shebang line लगाई जाती है
    • सच में जानना चाहता हूँ कि कौन-से pitfalls थे
      Pipenv में तब समस्या आई थी जब किसी खास dependency के अलग-अलग platforms के लिए अलग wheels थे, जबकि Poetry में यह ठीक काम करता था
      Pipenv की lock file में केवल उस platform की dependencies शामिल थीं जिस पर lock किया गया था, लेकिन Poetry सभी platform variants को lock file में जोड़ देता है
      uv इस मामले में कैसे behave करता है, इस पर documentation मुझे अभी तक नहीं मिला
  • मुख्य बात यह है
    हाल ही में प्रकाशित PEP यह define करता है कि Python scripts शुरुआती comments में dependencies कैसे declare करें, और uv एक Python script runner और package manager है जो उन dependencies को scan करके पूरा करता है और फिर script को इस स्थिति में चलाता है कि वे modules import किए जा सकें
    Python script की पहली line वाले comment, यानी shebang में python के बजाय file को uv से call कराने पर, script “execute” करते समय यह effect अपने-आप मिल जाता है
    नतीजा यह है कि जिन Python scripts को dependencies की setup चाहिए, वे भी बस चल जाती हैं

    • हाँ, $PATH में uv installed होना चाहिए
      और uv dependencies तो install करेगा, लेकिन इस तरीके से Python interpreter भी अपने-आप install करता है या नहीं, यह साफ नहीं है
    • आखिरकार system में uv install करने और हर script के आगे dependency lines जोड़ने के बाद ही वह “बस चलती” है
      व्यक्तिगत रूप से मुझे यह पुराने तरीके से environment बनाकर call करने की तुलना में समय बचाने वाला नहीं दिखता
      यह भी ठीक से नहीं पता कि uv interactive session में environment load कर सकता है या केवल script execution के लिए ही इस्तेमाल होता है
  • अगर आपको TypeScript पसंद है, तो Deno के साथ भी यही तरीका इस्तेमाल किया जा सकता है। Bun से भी शायद हो जाए, लेकिन मैंने खुद try नहीं किया
    #! /usr/bin/env -S deno run की तरह लिखें, और अगर permission flags चाहिए हों तो #! /usr/bin/env -S deno run --allow-env --allow-read --allow-net की तरह जोड़ दें

    • मैं Deno पसंद करता हूँ और यह तरीका इस्तेमाल कर रहा हूँ, लेकिन उम्मीद है कि वे इस बेवकूफी भरे bug को ज़रूर fix करेंगे: https://github.com/denoland/deno/issues/16466