- छोटे API टेस्ट स्क्रिप्ट के लिए भी dependencies की वजह से execution environment मिलाना पड़ता है, लेकिन uv execution shebang का उपयोग करने पर इसे बिना installation प्रक्रिया के सीधे चलने योग्य बनाया जा सकता है
- उदाहरण
jam_users.py, Go API के /users endpoint को टेस्ट करने के लिए httpx, IPython, loguru के साथ users को delete और create करने के बाद REPL में प्रवेश करता है
- पारंपरिक तरीके में system Python पर packages को global install करना पड़ता है या virtual environment अलग से तैयार करना पड़ता है, इसलिए script share करना और दोबारा चलाना असुविधाजनक होता है
# /// script header में dependencies = ["ipython", "httpx", "loguru"] घोषित करके uv run jam_users.py चलाने पर uv isolated environment और dependency installation को संभाल लेता है
#!/usr/bin/env -S uv run --script shebang और execution permission जोड़ने पर, Unix सिस्टम में सिर्फ uv installed हो तो ./jam_users.py की तरह चलाया जा सकता है
स्क्रिप्ट के अंदर dependencies घोषित करना
- उदाहरण
jam_users.py local API http://localhost:4000/v1/users के लिए test user data तैयार करता है
- httpx से API requests भेजता है
- IPython REPL में प्रवेश करके response देखता है और testing जारी रखता है
loguru से delete और create logs छोड़ता है
- बेसिक स्क्रिप्ट का flow user list को reset करने के बाद test data फिर से भरने का है
GET /v1/users से मौजूदा user list लाता है
- हर user के लिए
DELETE /v1/users/{id} कॉल करता है
- तैयार की गई user list को
POST /v1/users पर JSON के रूप में भेजता है
- उसके बाद
IPython.embed() से REPL खोलता है
python jam_users.py से चलाने के लिए httpx, IPython, loguru execution environment में पहले से installed होने चाहिए
- system Python पर global install करने या virtual environment अलग बनाने के तरीके भी हैं, लेकिन दोनों में run करने से पहले तैयारी चाहिए
- global install से system Python package clutter हो सकता है
- virtual environment वाले तरीके में create, activate, install, run प्रक्रिया को खुद manage करना पड़ता है
- दोनों तरीकों में compatible system Python और ज़रूरी packages उपलब्ध होने चाहिए
uv से सीधे executable स्क्रिप्ट बनाना
- uv का
# /// script टैग स्क्रिप्ट के ऊपर जोड़ने से file के अंदर dependencies घोषित की जा सकती हैं
# /// script
# dependencies = ["ipython", "httpx", "loguru"]
# ///
- यह header होने पर
uv run jam_users.py से चलाया जा सकता है
- uv script के लिए isolated virtual environment बनाता है
- ज़रूरी dependencies को download और install करता है
- उसी virtual environment context में script चलाता है
- सामान्य Python shebang
#!/usr/bin/env python में Python, # /// script comments को ignore कर देता है, इसलिए uv के script header का उपयोग नहीं हो पाता
- shebang में सीधे uv call डालने पर script को executable file की तरह treat किया जा सकता है
#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["ipython", "httpx", "loguru"]
# ///
env का -S flag बाद की string को अलग arguments में बाँटकर env को पास करता है
chmod +x jam_users.py से execution permission देने के बाद इसे इस तरह सीधे चलाया जा सकता है
./jam_users.py
- यह तरीका Unix सिस्टम में अगर uv installed है तो अलग dependency installation या virtual environment management के बिना script चलाने देता है
- जटिल Python scripts को दूसरे users तक पहुँचाते समय, run करने से पहले लंबी system setup प्रक्रिया समझाने का बोझ कम किया जा सकता है
1 टिप्पणियां
Hacker News की राय
UV खुद नहीं, बल्कि कुल मिलाकर comments के जरिए code execution को control करने का तरीका खटकता है
linter directives या developer notes के लिए comments इस्तेमाल करना ठीक है, लेकिन अगर बात configuration या execution-related data की है, तो
UV_ENV = { "dependencies": { "requests": "2.32.3", "pandas": "2.2.3" } }जैसा रूप कहीं बेहतर लगता हैयह तरीका valid Python syntax है, arbitrary comments parse करने के बजाय standard data structures इस्तेमाल करता है, इसलिए generate और validate करना आसान है, और सबसे बढ़कर यह सिद्धांत बनाए रखता है कि सारे comments हटाने पर भी code उसी तरह चलना चाहिए
आपके सुझाए तरीके में भी runtime पर कुछ नहीं करने वाला एक magic constant है, इसलिए वह सिर्फ static analysis से parse होगा, और uv के पढ़ने के बजाय कोई दूसरा tool उसे unused code मानकर हटा भी सकता है
इसके बजाय
import uvके बादuv.exec(dependencies=["clown"], python=">=3.10")जैसा कुछ लिखकर uv को सीधे बताना चाहिए कि क्या करना हैपहली execution किसी भी ऐसे Python runtime में हो जो इस काल्पनिक
uvpackage को ढूंढ सके, और फिरuvpackage virtual environment और Python runtime तैयार करने के बाद environment variable जैसे flag के साथre-exec(3)कर देदूसरे runtime में flag detect करने पर
uv.execकुछ भी न करे, बस इतना काफी होगाhttps://peps.python.org/pep-0723/
और shebang line खुद भी असल में comment की तरह ही काम करती है
45 साल से यह इतनी गहराई से जम चुकी है कि लोग यह बात ज्यादा महसूस ही नहीं करते कि वह shell comment है
अगर वही dependencies install की गई हों, तो code उसी तरह चलेगा
यह code के अपने meaning को बदलने के बजाय उस environment को बदलता है जिसमें code चलता है, और इस लिहाज से यह shell script के ऊपर लिखे
#!/bin/bashcomment से अलग नहीं हैहालांकि uv शायद dependencies पता करने के लिए code execute नहीं करना चाहेगा, इसलिए यह Python syntax का बहुत सीमित subset होना चाहिए
शुरुआत में ही ऐसी चीज की जरूरत होना language की कमजोरी दिखाता है
importstatement को खुद dependency के बारे में सारी जानकारी दे पाने में सक्षम होना चाहिएपिछले कुछ महीनों में HN पर यह topic बहुत बार आया है, और हाल के उदाहरण ये हैं
https://news.ycombinator.com/item?id=43500124
https://news.ycombinator.com/item?id=42463975
uv पसंद है, लेकिन self-contained शब्द से दो वजहों से सहमत होना मुश्किल है
पहली, script चलाने के लिए uv पहले से installed होना चाहिए
shell script से यह check कराया जा सकता है कि uv installed है या नहीं, और न हो तो curlpipe से install कराया जा सकता है, लेकिन इससे boilerplate काफी बढ़ जाता है और curlpipe तरीका अपने आप में भी अच्छा नहीं है
दूसरी, home directory में कहीं virtual environment automatically create करना सच में self-contained नहीं है
एक बार चलाकर script delete कर दें, तब भी वह virtual environment बचा रहता है और space लेता है, और uv docs में मुझे ऐसी कोई guarantee नहीं मिली कि ऐसे temporary virtual environments अपने-आप clean up होते हैं
curl | shइस्तेमाल करना होगाहालांकि package managers जैसे-जैसे uv को repositories में शामिल करने लगेंगे, यह समस्या धीरे-धीरे कम होगी
उदाहरण के लिए uv पहले से Alpine Linux और Homebrew में उपलब्ध है: https://repology.org/project/uv/versions
साथ ही inline script metadata Python standard है
अगर system में uv नहीं है और वह packaged भी नहीं है, लेकिन script के लिए सही Python version मौजूद है, तो pipx से चलाया जा सकता है: https://pipx.pypa.io/stable/examples/#pipx-run-examples
pipx कहीं ज्यादा व्यापक रूप से packaged है: https://repology.org/project/pipx/versions
किसी random developer machine पर uv की तुलना में Docker ज्यादा आम हो सकता है, और मूल लेख भी company project की बात कर रहा था, इसलिए यह plausible लगा
हालांकि अभी यह बिल्कुल caching नहीं करता, इसलिए हर run पर download होता है, जो अटपटा है; शायद volume से इसे ठीक किया जा सकता है
कुछ ऐसा है: https://hugojosefson.github.io/docker-shebang/#python
फिर भी अगर run करते समय internet से कोई अनजान चीज download होती है, तो उसे self-contained कहना मुश्किल है, और सच में पूरी तरह self-contained चीज AppImage के ज्यादा करीब है
py2exe जैसी चीज इस्तेमाल करें तो self-contained “Python script” बनाई जा सकती है
developer के लिए कई problems पैदा होती हैं, लेकिन user के लिए problems कम से कम रहती हैं
Nix से भी यही तरीका इस्तेमाल होता है, और shebang लाइन ऐसी दिखती है
#! nix-shell -i python3 -p "python312.withPackages (pkgs: [ pkgs.boto3 pkgs.click ])"ऐसा करने पर सिस्टम में सिर्फ Nix चाहिए, Python इंस्टॉल होना भी जरूरी नहीं
सबसे obvious उदाहरण ऐसा bash है जिसमें सभी dependencies निर्दिष्ट हों, और मैंने Nix shebang से तेज single-file Rust script भी बनाई है
https://nixos.wiki/wiki/Nix-shell_shebang
nix-shellके बजाय flake-आधारित commandnix shellसे वही काम कैसे किया जाए, यह जानने में दिलचस्पी हैबाकी comments की तरह “self-contained” वाला दावा इस पर निर्भर है कि
uvइंस्टॉल होअगर सच में self-contained Python script चाहिए, तो Nuitka compiler देखने लायक है
इसे gRPC service production में बिना समस्या इस्तेमाल कर रहा हूं, और बस
nuitka --onefile run.pyचलाना काफी हैcompiler होने के कारण result binary, PyInstaller से bundle किए गए मूल Python program से तेज भी हो सकती है
लेखक के GitHub page पर लिखा है, “संभव सबसे अच्छा Python Compiler बनाने के लिए बूढ़ा होकर मरने तक कोशिश करना मेरे जीवन का mission है”
https://nuitka.net/
https://github.com/kayhayen
यह pattern सच में पसंद है, लेकिन अफसोस कि इसे LSP के साथ ठीक से चला नहीं पाया
Helix में pyright इस्तेमाल कर रहा हूं, और editor को
uv run hx script.pyसे चलाने पर भी काम नहीं करताuv run --with whatever-it-is-i-need hx script.pyजैसा कर सकते हैं, लेकिन duplication बढ़ती जाती हैuvescript इस्तेमाल कर रहा हूं$ cat ~/.local/bin/uve#!/bin/bashtemp=$(mktemp)uv export --script $1 --no-hashes > $tempuv run --with-requirements $temp vim $1unlink $tempअच्छा होगा अगर editor जल्द ही
uv python find --scriptsupport करेकाफी उपयोगी लगता है
Python-based projects को long-term deploy करते समय uv ज्यादा सुरक्षित विकल्प है या नहीं, यह सोच रहा हूं
करीब 5 साल पहले dependency management के लिए Anaconda इस्तेमाल किया था, फिर बाद में rules बदल गए और 200 से ज्यादा employees वाले संगठनात्मक customers अब Anaconda मुफ्त में इस्तेमाल नहीं कर सकते थे, commercial license लेना पड़ता था—वही rug pull याद आ रहा है
वे development बंद कर सकते हैं या आगे का काम किसी दूसरे license वाले fork में ले जा सकते हैं, लेकिन पुराने license को retroactively बदल नहीं सकते, इसलिए जो अभी मौजूद है वह open source होने की guarantee रखता है
अगर सच में चिंता है, तो fork बनाकर sync करते रह सकते हैं
असल में यही बात लगभग दूसरे OSS projects पर भी लागू होती है, इसलिए मैं ज्यादा चिंता नहीं करूंगा
मेरी जानकारी में conda कभी open source नहीं था और binaries distribute करता रहा है
https://github.com/astral-sh/uv?tab=readme-ov-file#license
conda-forge के packages अभी भी मुफ्त में इस्तेमाल किए जा सकते हैं
uv तो बस PyPI इस्तेमाल करता है, इसलिए समस्या हो तो uv से pip या Poetry वगैरह पर switch कर सकते हैं, और packages अब भी उसी जगह से आते रहेंगे
ऐसा owner अंततः कल्पना किए जा सकने वाले सबसे बुरे अमीर व्यक्ति द्वारा खरीद लिया जाएगा
मैंने uv की contribution guide और issues सरसरी तौर पर देखे, लेकिन CLA नहीं दिखा, जबकि PyTorch की contribution guide के सबसे ऊपर CLA था
फिर भी Anaconda के आखिरी FOSS version का community fork होना चाहिए था
Redis में ऐसा हुआ, और Redis भी CLA इस्तेमाल करता है: https://github.com/redis/redis/blob/unstable/CONTRIBUTING.md#redis-software-grant-and-contributor-license-agreement
CLA पर कभी sign नहीं करना चाहिए
मेरे हिसाब से बेहतर है कि केवल copyleft projects में ही contribute करें
हम मुफ्त में काम करने के लिए बहुत ज्यादा पैसा कमाते हैं
छोटी utilities के लिए containerization के बजाय यह अच्छा packaging alternative लगता है
अब सभी colleagues को uv install करने के लिए मनाना पड़ेगा
Ruby के bundler/inline जैसा लगता है
अच्छा है कि Python में भी कुछ ऐसा आया, और सच में बहुत सुविधाजनक है
https://bundler.io/guides/bundler_in_a_single_file_ruby_script.html
जानना चाहूंगा कि क्या Windows पर किसी ने इसे चलाया है
जिस गेम मोड टूल पर मैं काम कर रहा हूं, उसमें यह ट्रिक इस्तेमाल करना चाहता था, लेकिन shebang ट्रिक चला नहीं पाया
$> uv init --script .py$> uv add --script .py ...$> uv add --script .py --dev ...$> uv run .pyउम्मीद है मदद मिलेगी
स्रोत: https://docs.astral.sh/uv/guides/scripts/
.pyfiles से associate करता हैpy launcher shebang line को support करता है
कुछ दिन पहले इसी topic पर आए एक blog post में भी इसे cover किया गया था, और उसके मुताबिक
-Sहटाना होगा: https://thisdavej.com/share-python-scripts-like-a-pro-uv-and-pep-723-for-easy-deployment/https://news.ycombinator.com/item?id=43500124
खुद try नहीं किया, इसके बजाय file association बदल दी ताकि सभी
.pyfiles default रूप सेuv runसे खुलेंhttps://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 की वजह से मुझे uv पसंद आने लगा, लेकिन यह बात Zen of Python के खिलाफ लगती है कि एक official और बहुत useful PEP को official Python tools support नहीं करते
मेरे नज़रिए से यह वह पहला पल था जब Python “batteries included” नहीं लगा
अब system में Python dependency managers भी दो हो गए हैं
मुझे पता है कि Python dependency management पर कहने को बहुत कुछ है, लेकिन पिछले कुछ सालों में अगर project में सिर्फ
requirements.txtहोता था, तो मैं defaultpip+venvसे काम चला लेता थायाद है कि
pyproject.toml,tomlliblibrary से पहले आया थाइसलिए कुछ versions तक modules को ऐसी भाषा में specify करना पड़ता था जिसे Python default रूप से पढ़ नहीं सकता था
यह उस default तरीके से भी खराब स्थिति है जिसमें unused metadata शामिल होता है
आखिर इसी वजह से वह metadata है, वरना बस Python syntax होता