पायथन में एन्वायरनमेंट वेरिएबल्स का उपयोग: os.environ, os.environb और क्रॉस-प्लेटफ़ॉर्म विचार
पायथन में os.environ और os.environb का उपयोग करके एन्वायरनमेंट वेरिएबल्स को कैसे पढ़ें, संशोधित करें और सिंक करें, प्लेटफ़ॉर्म के बीच एन्कोडिंग अंतरों को संभालें और बच्चे प्रक्रियाओं को एन्वायरनमेंट पास करें।
इस पृष्ठ पर
संक्षिप्त उत्तर
os.environ इंटरप्रीटर स्टार्टअप पर कैप्चर की गई प्रोसेस एन्वायरनमेंट की एक डिक-जैसी स्नैपशॉट है। इसे म्यूटेट करने से setenv या unsetenv स्वतः कॉल होता है, लेकिन os.putenv मैपिंग को अपडेट नहीं करता है। यूनिक্স पर, os.environb os.environ के साथ सिंकराइज़्ड बाइट्स व्यू प्रदान करता है। कुंजी और मानों का एन्कोडिंग फ़ाइल सिस्टम एन्कोडिंग या यूटीएफ-8 मोड पर निर्भर करता है। os.reload_environ (पायथन 3.14+) बाहरी परिवर्तनों के बाद कैश को रीफ्रेश करता है लेकिन थ्रेड-सुरक्षित नहीं है। बच्चे प्रक्रियाएं spawn*/exec* फ़ंक्शंस के env पैरामीटर के माध्यम से एन्वायरनमेंट प्राप्त करती हैं, जिसमें स्ट्रिंग कुंजी और मान होने चाहिए।
os.environ और os.getenv के माध्यम से एन्वायरनमेंट वेरिएबल्स को पढ़ना
os.environ प्रोसेस एन्वायरनमेंट का प्रतिनिधित्व करने वाला मैपिंग ऑब्जेक्ट है। एक ऐसी कुंजी को एक्सेस करना जो मौजूद नहीं है, KeyError उत्पन्न करता है, जबकि os.environ.get(key, default) डिफ़ॉल्ट लौटाता है। os.getenv(key, default=None) एक कन्वेंसियन व्रापर है जो वैरिएबल अनुपस्थित होने पर None भी लौटाता है। महत्वपूर्ण भेद एक ऐसे वैरिएबल के बीच है जो सेट नहीं है (None लौटाता है) और एक ऐसा जो खाली स्ट्रिंग पर सेट है ('' लौटाता है)। परिणाम की सत्यता का उपयोग इन दोनों स्थितियों को मिलान करता है, जो उत्पादन विस्तार में कॉन्फ़िगरेशन त्रुटियों को चुपचाप छिपा सकता है।
स्रोत दस्तावेज़ीकरण बताता है कि environ एक मैपिंग है जहाँ कुंजी और मान दोनों स्ट्रिंग होते हैं। उन प्लेटफ़ॉर्म पर जो बाइट्स एन्वायरनमेंट एक्सेस का समर्थन करते हैं, बाइट्स प्रतिनिधित्व os.environb और os.getenvb के माध्यम से उपलब्ध है। अधिकांश अनुप्रयोग कोड के लिए, os.environ या os.getenv पर्याप्त है क्योंकि इंटरप्रीटर फ़ाइल सिस्टम एन्कोडिंग या यूटीएफ-8 मोड से स्वतः डिकोडिंग संभालता है।
import os
# Distinguish absent from empty
value = os.environ.get("APP_MODE")
if value is None:
print("variable not set")
else:
print("value:", repr(value))व्यावहारिक सुझाव
जब आपको यह पता लगाना हो कि कोई वेरिएबल वास्तव में अनुपस्थित है या खाली स्ट्रिंग पर सेट है, तो os.environ.get(name) का उपयोग करें और None की जाँच करें, क्योंकि खाली स्ट्रिंग फॉल्सी है परंतु अर्थतः अलग है।
os.environ के माध्यम से वेरिएबल्स को संशोधित और हटाना
os.environ[key] को असाइन करने से underlying setenv सिस्टम फ़ंक्शन कॉल होता है। एक कुंजी को हटाने से unsetenv कॉल होता है। pop() और clear() विधियाँ भी हटाई गई प्रत्येक प्रविष्टि के लिए unsetenv ट्रिगर करती हैं। यह स्वतः सिंकरोनाइज़ेशन ही वह कारण है कि दस्तावेज़ीकरण os.environ को संशोधित करने की सलाह देता है बजाय सीधे os.putenv कॉल करने के, क्योंकि putenv C-लेवल environ एरे में लिखता है बिना पायथन मैपिंग को अपडेट किए, जिससे os.environ पुराना रह जाता है।
कुछ प्लेटफ़ॉर्म पर, जिसमें FreeBSD और macOS शामिल हैं, setenv या putenv के बार-बार कॉल करने से C रनटाइम में मेमोरी लीक हो सकते हैं। यह एक प्लेटफ़ॉर्म-स्तर का चिंतन है न कि पायथन बग, लेकिन इसका मतलब है कि लंबे समय तक चलने वाली प्रक्रियाएं जो बार-बार एन्वायरनमेंट वेरिएबल्स को संशोधित करती हैं, उन्हें अपने द्वारा बनाई जाने वाली विशिष्ट कुंजियों की संख्या को कम करना चाहिए।
import os
os.environ["APP_MODE"] = "production" # calls setenv
os.environ.pop("APP_MODE", None) # calls unsetenv if presentos.environ और os.environb का सिंकरोनाइज़ेशन
os.environb एक बाइट्स-वर्जन मैपिंग है जो केवल तभी उपलब्ध है जब os.supports_bytes_environ True है, जो यूनिक्स प्लेटफ़ॉर्म पर सत्य होता है। दो मैपिंग्स को सिंक रखा जाता है: environb को संशोधित करने से environ अपडेट होता है और इसके विपरीत। इसका मतलब है कि आप environb में एक बाइट्स मान लिख सकते हैं और environ से डिकोडेड स्ट्रिंग पढ़ सकते हैं, या इसके विपरीत। विंडोज़ पर, supports_bytes_environ False है और environb मौजूद नहीं है, इसलिए दोनों प्लेटफ़ॉर्म को टार्गेट करने वाले कोड को उस फ़्लैग के साथ एक्सेस को गार्ड करना चाहिए।
सिंकरोनाइज़ेशन फ़ाइल सिस्टम एन्कोडिंग और इसके एरर हैंडलर का उपयोग बाइट्स और str के बीच रूपांतरण के लिए करता है। यदि एक बाइट्स मान में ऐसे अनुक्रम हैं जो वर्तमान एन्कोडिंग के तहत डिकोड नहीं किए जा सकते, तो surrogateescape str व्यू में अकेले सुरुगेट उत्पन्न करता है। दोनों प्रतिनिधित्वों के माध्यम से राउंड-ट्रिपिंग मूल बाइट्स को संरक्षित करती है।
import os
if os.supports_bytes_environ:
os.environb[b"RAW_KEY"] = b"\xff\xfe"
print(os.environ["RAW_KEY"]) # decoded via fsencode/fsdecodeएन्कोडिंग: यूटीएफ-8 मोड, fsencode/fsdecode, और getenvb
जब पायथन यूटीएफ-8 मोड सक्रिय होता है (-X utf8 या PYTHONUTF8=1 के माध्यम से सक्षम किया गया, या स्वतः जब लोकेल C या POSIX है), एन्वायरनमेंट वेरिएबल्स सिस्टम लोकेल की परवाह किए बिना यूटीएफ-8 का उपयोग करके डिकोड किए जाते हैं। यूटीएफ-8 मोड के बाहर, फ़ाइल सिस्टम एन्कोडिंग डिकोडिंग को नियंत्रित करता है। os.fsencode और os.fsdecode इन रूपांतरणों को स्पष्ट रूप से उजागर करते हैं और पथ-जैसे बाइट्स को संभालने के लिए अनुशंसित तरीका हैं जो एन्वायरनमेंट मानों में दिखाई दे सकते हैं।
os.getenvb किसी भी डिकोडिंग चरण के बिना एन्वायरनमेंट वेरिएबल के कच्चे बाइट्स लौटाता है। यह उपयोगी है जब आपको ऐसे मानों को निरीक्षण या आगे बढ़ाने की आवश्यकता होती है जो वर्तमान एन्कोडिंग के तहत अमान्य बाइट्स हो सकते हैं, या जब पोर्टेबल कोड लिखना है जो स्पष्ट डिकोड-फिर-री-एन्कोड राउंड ट्रिप से बचना चाहिए।
import os, sys
print("filesystem encoding:", sys.getfilesystemencoding())
print("utf8 mode:", sys.flags.utf8_mode)
# Raw bytes access (Unix only)
if os.supports_bytes_environ:
raw = os.getenvb(b"LANG")
print("LANG bytes:", raw)पर्यावरण कैश और os.reload_environ
दस्तावेज़ीकरण स्पष्ट है: os.environ और os.environb वह समय हैं जब पायथन शुरू हुआ था तब पर्यावरण चरों का एक कैश है। इंटरप्रीटर के बाहर बनाई गई या os.putenv और os.unsetenv के माध्यम से की गई परिवर्तन मैपिंग में प्रतिबिंबित नहीं होते हैं। os.reload_environ, जो Python 3.14 में जोड़ा गया था, वर्तमान प्रोसेस पर्यावरण से दोनों मैपिंग को ताज़ा करता है। 3.14 से पहले, बाहरी संशोधन के बाद कैश को पुनः सिंक करने का कोई मानक तंत्र मौजूद नहीं था।
इसका महत्व उन परिदृश्यों में होता है जहाँ एक पैरेंट प्रोसेस या सिग्नल हैंडलर सी-लेवल एपीआई के माध्यम से वातावरण को संशोधित करता है, या जब कोई लाइब्रेरी os.environ के माध्यम जाने बिना putenv को कॉल करती है। reload_environ के बिना, बाद के पढ़ने में पुराने मान लौटाए जाते हैं।
import os
# After external modification of the process environment:
os.reload_environ() # Python 3.14+
print(os.environ.get("EXTERNALLY_SET_VAR"))त्रुटियाँ और पर्यावरण के साथ काम करते समय थ्रेड सुरक्षा
os मॉड्यूल में सभी फ़ंक्शन OSError या एक उपकक्षा उत्पन्न करते हैं जब तर्क सही प्रकार के होते हैं लेकिन ऑपरेटिंग सिस्टम द्वारा अस्वीकार कर दिए जाते हैं। पर्यावरण संचालन के लिए यह दुर्लभ है क्योंकि setenv और unsetenv वैध स्ट्रिंग्स के लिए सफल हो जाते हैं, लेकिन कुंजी या मानों में अमान्य सर्फोगेट वर्ण UnicodeEncodeError को ट्रिगर कर सकते हैं।
os.reload_environ में एक स्पष्ट चेतावनी है कि यह थ्रेड-सुरक्षित नहीं है। os.environ, os.environb से पढ़ना या os.getenv को कॉल करना जब रीलोड चल रहा हो खाली परिणाम लौटा सकता है। बहु-थ्रेडेड अनुप्रयोगों में, reload_environ के लिए पहुंच को सीरियलाइज़ करें या इसे पूरी तरह से टालें और केवल os.environ परिवर्तन के माध्यम से पर्यावरण स्थिति का प्रबंधन करें।
import os
try:
os.environ["BAD_KEY"] = "value\ud800" # lone surrogate
except UnicodeEncodeError as e:
print("encoding error:", e)क्रॉस-प्लेटफ़ॉर्म पोर्टेबिलिटी: os.name, प्लेटफॉर्म सीमाएं और PATH
os.name यूनिक्स-जैसे सिस्टम पर 'posix' और विंडोज़ पर 'nt' लौटाता है। WebAssembly, Android और iOS पर, os मॉड्यूल के बड़े हिस्से अनुपलब्ध हैं या अलग व्यवहार करते हैं: fork, execve और spawn जैसे प्रोसेस एपीआई गायब हैं, और getuid और getpid स्टब्स हो सकते हैं। ऐसे लक्ष्यों पर चलने वाले कोड को प्लेटफॉर्म-विशिष्ट व्यवहार पर निर्भर रहने से पहले os.name और os.supports_bytes_environ की जांच करनी चाहिए।
os.get_exec_path निष्पाद्य खोजने के लिए खोजे जाने वाले निर्देशिकाओं की सूची लौटाता है, प्रदान किए गए env डिकशनरी या डिफ़ॉल्ट रूप से os.environ में PATH चर से पढ़ता है। यह शेल PATH खोज का प्रोग्रामेटिक समकक्ष है और p-variants के आंतरिक रूप से spawn और exec फ़ंक्शनों द्वारा उपयोग किया जाता है।
import os
print("os.name:", os.name)
print("supports_bytes_environ:", os.supports_bytes_environ)
print("exec paths:", os.get_exec_path())spawn और exec के माध्यम से बच्चे प्रक्रियाओं को पर्यावरण पास करना
spawn*e और exec*e वेरिएंट एक env पैरामीटर स्वीकार करते हैं जो बच्चे प्रक्रिया पर्यावरण को पूरी तरह से प्रतिस्थापित करता है बजाय पैरेंट से विरासत में लेने के। इस मैपिंग में कुंजी और मान स्ट्रिंग्स होने चाहिए; अमान्य प्रकार फ़ंक्शन को 127 के रिटर्न मान के साथ विफल कर देते हैं। जब env प्रदान किया जाता है, तो निष्पाद्य के लिए PATH खोज नए पर्यावरण का उपयोग करती है, न कि पैरेंट के os.environ का।
विरासत (spawnl, spawnv, execl, execv) और प्रतिस्थापन (spawnle, spawnlpe, spawnve, spawnvpe, execle, execvpe) के बीच यह अंतर बच्चे प्रक्रियाओं को सांडबॉक्स करने या पैरेंट पर्यावरण को दूषित किए बिना कॉन्फ़िगरेशन इंजेक्ट करने के लिए आवश्यक है।
import os
child_env = dict(os.environ)
child_env["APP_MODE"] = "production"
# spawnvpe replaces the child environment entirely
status = os.spawnvpe(os.P_WAIT, "cp", ["cp", "index.html", "/dev/null"], child_env)
print("exit status:", status)क्या जाँचें
- os.environ.get अनुपस्थित वैरिएबल्स के लिए None लौटाता है और '' उन वैरिएबल्स के लिए जो खाली स्ट्रिंग पर सेट हैं; ये None के साथ पहचान जांच द्वारा ही भेद किए जा सकते हैं।
- os.environ[key] = value setenv कॉल करता है; del os.environ[key] unsetenv कॉल करता है; os.putenv os.environ को अपडेट नहीं करता है।
- os.environb केवल तभी मौजूद है जब os.supports_bytes_environ True है (यूनिक्स); एक मैपिंग को संशोधित करने से दूसरा अपडेट होता है।
- यूटीएफ-8 मोड एन्वायरनमेंट वेरिएबल्स का यूटीएफ-8 डिकोडिंग अनिवार्य करता है लोकेल की परवाह किए बिना; sys.flags.utf8_mode की जांच करें।
- os.reload_environ पायथन 3.14 से उपलब्ध है और थ्रेड-सुरक्षित नहीं है; समानांतर पठन खाली परिणाम लौटा सकते हैं।
- spawn*e और exec*e में env पैरामीटर में स्ट्रिंग कुंजी और मान होने चाहिए; अमान्य प्रविष्टियाँ 127 वापसी मान का कारण बनती हैं।
- WebAssembly, Android और iOS पर, प्रक्रिया-संबंधी os फ़ंक्शंस अनुपलब्ध या स्टब किए गए हैं।
उपयोग की सीमाएँ
os.environb और os.getenvb केवल यूनिक्स-विशिष्ट हैं (supports_bytes_environ द्वारा गेटेड)। os.reload_environ को पायथन 3.14 या बाद की आवश्यकता है और स्पष्ट रूप से थ्रेड-सुरक्षित नहीं है। FreeBSD और macOS पर, बार-बार setenv कॉल करने से C लेवल पर मेमोरी लीक हो सकती है। यूटीएफ-8 मोड केवल इंटरप्रीटर स्टार्टअप पर सक्षम किया जा सकता है और रनटाइम पर टॉगल नहीं किया जा सकता। spawn/exec फ़ंक्शंस WebAssembly, Android और iOS पर अनुपलब्ध हैं।