Python की जगह Go से scripting करना
(lorentz.app)- Go फ़ाइलों को executable की तरह सीधे चलाने की एक ट्रिक का परिचय
- पहली पंक्ति में
//usr/local/go/bin/go run "$0" "$@"; exitरखें और execute permission दें, तो./script.goसे चलाया जा सकता है - यह तरीका shebang नहीं है, बल्कि POSIX में ENOEXEC होने पर shell के /bin/sh पर fallback करने वाले व्यवहार का उपयोग करता है
- shell पहली पंक्ति को command की तरह चलाता है, और Go compiler उसे
//comment मानकर नज़रअंदाज़ कर देता है "$0"से अपनी ही path पास की जाती है, इसलिएgo runscript को build और execute करता है, और$@से arguments पास होते हैं- Go की मज़बूत standard library और backward compatibility की गारंटी इसे scripting के लिए उपयुक्त बनाती है, और Go 1.x version इस्तेमाल करने पर script दशकों तक चल सकती है
- Python के virtual environment, pip/poetry/uv जैसी dependency management की जटिलता से बचा जा सकता है
नकली shebang कैसे काम करता है
- shebang(
#!) execve system call के ज़रिए interpreter तय करने का तरीका है, लेकिन यहाँ बताई गई तकनीक shebang नहीं है - Go source file की पहली पंक्ति में
//usr/local/go/bin/go run "$0" "$@"; exitरखकर, उसके नीचेpackage mainऔर सामान्य Go code लिखा जाता हैchmod +x script.goसे execute permission देने पर इसे./script.goकी तरह चलाया जा सकता है
straceसे देखने पर पता चलता है कि shell जब./script.goकोexecveसे चलाने की कोशिश करता है, तो kernel ENOEXEC(Exec format error) लौटाता है- ENOEXEC मिलने पर shell fallback के तौर पर
/bin/shका उपयोग करके उसी फ़ाइल को shell script की तरह interpret करता है - shell में
//comment नहीं है, बल्कि root path(/) की तरह interpret होता है, इसलिए//usr/local/go/bin/goएक वैध path की तरह execute हो जाता है
- ENOEXEC मिलने पर shell fallback के तौर पर
- इसलिए पहली पंक्ति
//usr/local/go/bin/go run "$0" "$@"; exitshell में command की तरह execute होती है"$0"execute की गई फ़ाइल का path देता है, इसलिए command में"$0"script.gopath बन जाता है औरgo runउसी फ़ाइल को ढूँढकर build और execute करता है"$@"positional arguments expansion है, जिससे./script.go -f flag0 here are some argsजैसी invocation संभव होती है; exitन हो तोshGo फ़ाइल को आगे भी लाइन-दर-लाइन interpret करता रहेगा औरpackageजैसे token पर error देगा
Go scripting के लिए उपयुक्त क्यों है
- Go की backward compatibility की गारंटी इसकी मुख्य विशेषताओं में से है, इसलिए Go 1.x इस्तेमाल करने पर लिखी गई script लंबे समय तक चलती रहती है
- अच्छी तरह विकसित standard library और built-in tools (formatter, linter आदि) बिना अलग setup के मिलते हैं, जिससे script sharing और portability अधिकतम हो जाती है
- Python की तरह virtual environment या अलग-अलग package managers (pip, poetry, uv) सीखे बिना code चलाया जा सकता है
- Go ecosystem के built-in tools और IDE integration की वजह से
.pyprojectयाpackage.jsonके बिना भी formatter और linter डिफ़ॉल्ट रूप से इस्तेमाल किए जा सकते हैं
- अगर सिर्फ़ नया Go installed हो, तो किसी भी OS पर दशकों तक चलाया जा सकता है
दूसरी compiled languages से तुलना
- Rust में compile speed धीमी है, standard library अपेक्षाकृत कमज़ोर है, dependency का उपयोग लगभग अनिवार्य हो जाता है, और perfectness पर ज़ोर होने से development speed धीमी पड़ती है
- Java और JVM भाषाओं में पहले से JVM bytecode आधारित scripting languages मौजूद हैं, और हल्की Kotlin scripting भी एक विकल्प हो सकती है
- compiled languages में Go के पास scripting use case के लिए सबसे उपयुक्त गुण हैं
gopls formatting समस्या और समाधान
goplscomment के बाद space मांगता है (//example→// example), इसलिए नकली shebang लाइन टूट जाती है- space आ जाने पर
// usr/local/go/bin/goबन जाता है, जिसे shell path की तरह नहीं पहचानता - समाधान: HN thread के सुझाव के अनुसार
//की जगह/**/block comment का उपयोग करें- इसे
/*usr/local/go/bin/go run "$0" "$@"; exit; */के रूप में लिखा जा सकता है exitके बाद semicolon(;) अनिवार्य है
- इसे
1 टिप्पणियां
Hacker News की राय
लेखक ने जो “pip vs poetry vs uv की चिंता नहीं” वाली बात कही, दरअसल uv इस use case को सीधे support करता है
PyPI dependencies सहित, बस Python version और uv installed होना चाहिए
uv आधिकारिक दस्तावेज़ लिंक
#!/usr/bin/env -S uv run --python 3.14 --scriptऐसा करने पर Python खुद installed न हो तब भी uv तय किया गया version डाउनलोड करके चला देता है
Clojure को पहली बार सीखते समय ज़्यादातर लोग Leiningen इस्तेमाल करने की सलाह सुनते हैं, लेकिन Python में search करो तो venv, poetry, hatch, uv जैसी कई चीज़ें सामने आती हैं
uv धीरे-धीरे main choice बन रहा है, लेकिन अभी universal नहीं है
मैंने पहले Go को apt से install किया था और version बहुत पुराना निकला, तो दोबारा install करना पड़ा था, लेकिन वह समस्या इससे कहीं जल्दी हल हो गई
Python के virtual environment की समस्या अब भी जटिल है
यह Rust में लिखा OSS tool है, जो Python version और venv को अपने-आप manage करता है
बस
pyproject.tomlसेट करो औरpyflow main.pyचलाओ, तो यह Cargo की तरह dependency install और lock करता है, और project के हिसाब से Python version भी अपने-आप match कर देता हैउस समय Poetry और Pipenv लोकप्रिय थे, लेकिन venv और version management तक उनकी पहुंच कमज़ोर थी
ज़्यादातर
uv addइस्तेमाल करता हूँ, और ज़रूरत पड़ने पर हीuv pipलेकिन
uv pip, pip की limitations उसी तरह रखता है — install order के हिसाब से dependency resolution बदल जाता हैuv pip install dep-aके बादdep-binstall करना, order उलटना, या दोनों को एक साथ install करना — सबके result अलग हो सकते हैंयह ज़्यादा pip की समस्या है, लेकिन Python package management का confusion अभी भी बना हुआ है
uv खुद डाउनलोड कर लेता है
Go ने shebang support को साफ़ तौर पर अस्वीकार किया है
इसके बजाय
gorunइस्तेमाल करने की सलाह दी जाती है/// 2>/dev/null ; gorun "$0" "$@" ; exit $?जैसी POSIX trick से इसे चलाया जा सकता हैNim, Zig, D में
-runoption से ऐसा ही किया जा सकता है, और Swift, OCaml, Haskell में file को सीधे execute किया जा सकता हैसंबंधित चर्चा लिंक
go runकी जगह yaegi interpreter बेहतर हो सकता हैyaegi GitHub
“मैं pip, poetry, uv का फर्क नहीं जानना चाहता, बस code चलाना चाहता हूँ” जैसी बात आखिरकार technical proficiency की समस्या है
uv runऔर PEP 723 पहले ही सारी समस्या हल कर चुके हैंuv runआने में बहुत देर हो गईमैं 20 साल से ज़्यादा समय से Python इस्तेमाल कर रहा हूँ, लेकिन external packages या venv वाले codebase हमेशा डराते रहे हैं
uv runकी वजह से मैंने company projects सब migrate कर दिए, लेकिन personal projects पहले ही Go पर चले गएलंबे समय में मैं statically typed languages को पसंद करता हूँ
user बस चाहता है कि program चल जाए
uv runऔर PEP 723 ने समस्या हल कर दी है, लेकिन uv के बारे में जानना पड़े, यह अब भी entry barrier हैजब तक uv official default tool नहीं बनता, बहुत से users Python छोड़ते रहेंगे
मुझे यह सच में genius idea लगता है
लेकिन scripting को deployment software से अलग तरह की ergonomics चाहिए
bash ad-hoc है, Go productization के लिए अच्छा है, Python बीच में कहीं है, Ruby bash के करीब है, और Rust Go की तरफ़ है
scripts OS commands को जल्दी-जल्दी जोड़कर one-off काम करने में काम आते हैं
Go में वह improvisation कम है
Debian में एक simple gtk app को uv से चलाने की कोशिश की थी, dependencies सब सही थीं, फिर भी नहीं चला और आखिर में Core Dump
Python को हर बार नए सिरे से आज़माने पर ऐसा कुछ हो ही जाता है
Go verbose है, लेकिन एक बार compile हो जाए तो बस चलता है
असली बात यह है कि क्या एक file में काम खत्म हो सकता है
Go में 500-line script भी हो सकती है, लेकिन language खुद multiple files और modules को मानकर चलती है
bang-line support न होना भी उसी वजह से है
वैसे भी अगर
go runअस्थायी binary बनाता ही है, तो मुझे लगता है सीधे build करके/usr/local/binमें डालना बेहतर हैbash भी Python की तरह OS के ऊपर एक abstraction layer ही है, बस default shell होने की वजह से ऐसा महसूस होता है
खासकर उस दिशा में जहाँ LLM द्वारा लिखा code इंसानों के लिए पढ़ने में आसान बनाया जाए
मैं इस बात से सहमत हूँ कि Python पहली बार सीखने वाले user को pip, poetry, uv का फर्क जानने की ज़रूरत नहीं होनी चाहिए
लेकिन अगर कोई ब्लॉगर इस विषय पर लिख रहा है, तो उसे कम-से-कम यह तो पता होना चाहिए कि uv इस समस्या का समाधान करता है
अनजान आलोचना persuasive नहीं होती
मैं भी uv के concept को पूरी तरह नहीं समझ पाया हूँ, इसलिए जानना चाहता हूँ
मुझे Python में scripting करना पसंद है
इसमें तेज़ी से काम हो जाता है, और type या memory की चिंता किए बिना simple काम करना आसान है
लेकिन बड़े application के लिए मैं इसे नहीं चुनना चाहूँगा
ज़्यादातर systems में default Python होता है, इसलिए simple scripts के लिए वह काफ़ी है
Go install करना पड़े, यह देखते हुए मुझे Python को uv के साथ इस्तेमाल करना ज़्यादा बेहतर लगता है
जैसा लेखक ने भी कहा कि “मैंने थोड़ा trolling की तरह शुरू किया था”, आख़िर में यह Go preference का मामला है
node bla.jsऔर काम खत्मfunction क्या return करता है, यह जानना होता है, और language अच्छी तरह आ जाए तो basic types याद से संभाल लिए जाते हैं
static type languages में भी यही बात लागू होती है
अगर आपको दूसरे लोगों का भी ध्यान रखना है, तो Python में deployable code नहीं लिखना चाहिए
मैं Python की आलोचना की उम्मीद कर रहा था, लेकिन यह तो उल्टा useful tip निकला
जिन languages में
//comment के रूप में चलता है, उनमें इस trick को अपनाया जा सकता हैC/C++, Java, JavaScript, Rust, Swift, Kotlin, ObjC, D, F#, GLSL आदि में यह संभव है
खासकर GLSL से single-file graphics demo बनाना दिलचस्प लगता है
Shadertoy उदाहरण
C में block comment का उपयोग करके
/*/../usr/bin/env gcc "$0" "$@"; ./a.out; rm -vf a.out; exit; */जैसा तरीका भी इस्तेमाल किया जा सकता हैयह Swift के लिए uv जैसी अवधारणा है
Swift आधिकारिक तौर पर shebang भी support करता है
#!सीधे भी लिखा जा सकता हैपुराने TCC दौर में मैंने “C scripting” के लिए यह तरीका इस्तेमाल किया था
बड़े projects में build script manifest पढ़कर build के बाद run करता था
लेकिन environment control कठिन होने के कारण यह practical work में ठीक नहीं बैठता
वह shebang को सीधे support करता है
अगर आपको और ergonomic language चाहिए, तो .NET 10 की “run file directly” feature भी है
यह shebang support करती है, और script के भीतर packages अपने-आप install कर देती है
#:sdkdirective से web app भी सीधे चलाया जा सकता हैबस AOT compilation अभी थोड़ी कच्ची है
शुरू में लगा था यह Python की आलोचना होगी, लेकिन इसने उल्टा language ecosystem की direction पर सोचने पर मजबूर कर दिया
मेरे हिसाब से ML का Python से बंध जाना बड़ी गलती थी
क्योंकि यह धीमा है, type system असुविधाजनक है, और deployment मुश्किल है
अब TypeScript, Go, Rust जैसे alternatives पर विचार करना चाहिए
लेकिन ML ने Python चुना, उसकी वजह C-based FFI थी
NodeJS, Rust, Go में FFI कमज़ोर है
Python यहाँ मज़बूत है
आदर्श रूप से हमें Python जितनी सरल, लेकिन बेहतर type system और deployment model वाली language चाहिए
JS ecosystem से निकली language से Python को replace नहीं करना चाहता
Lisp या Lua(Torch) ज़्यादा उपयुक्त थे, लेकिन simplicity की वजह से Python चुना गया
मैं भी Lisp-आधारित ML framework बना रहा हूँ, लेकिन adoption मुश्किल लगती है
version compatibility issues, semver की कमी, unstable ecosystem जैसी वजहों से यह JS से पीछे लगता है
JS/Node पिछले 10 साल में mature हुए हैं, लेकिन Python अभी भी 2012 में अटका लगता है
ML का Python पर standardize होना सच में अफ़सोस की बात है
CLI tools बनाते समय Go, Python से कहीं तेज़ है
LOC के फर्क की वजह से मैं Python पर लौट आता हूँ, लेकिन हर बार चलाते समय Go याद आता है
शायद OCaml आदर्श हो, लेकिन पुराना tooling बोझिल लगता है
Go scripts की समस्या यह है कि पहली line में कोई whitespace नहीं होना चाहिए
क्योंकि
goplsauto-formatting enforce करता हैCI में भी format consistency बनाए रखनी पड़ती है, इसलिए यह practical तौर पर महत्वपूर्ण है
लेकिन बड़ी समस्या यह है कि go.mod इस्तेमाल नहीं किया जा सकता
यानी dependency versions specify नहीं कर सकते, इसलिए compatibility guarantee कमज़ोर हो जाती है