Python में सापेक्ष पथ: टर्मिनल, IDE और सेवा लॉन्च
Python में सापेक्ष पथ का हल प्रक्रिया कार्य निर्देशिका पर निर्भर करता है, जो लॉन्चर के अनुसार बदलती है। इस गाइड में कार्य निर्देशिका की जाँच करना, स्पष्ट पथ आधार चुनना और यह समझना शामिल है कि __file__ हमेशा भरोसेमंद नहीं होता।
इस पृष्ठ पर
संक्षिप्त उत्तर
Path("data/config.json") जैसा सापेक्ष पथ आपके स्क्रिप्ट की स्थिति के बजाय प्रक्रिया के वर्तमान कार्य निर्देशिका के सापेक्ष हल किया जाता है। कार्य निर्देशिका वह है जो os.getcwd() रिपोर्ट करता है जब दुभाषिया शुरू होता है, और टर्मिनल, IDE और सेवा लॉन्चर आमतौर पर इसे अलग-अलग तरीके से सेट करते हैं। शुरूआत में Path.cwd() प्रिंट करें ताकि वास्तविक मान दिखे। फिर स्पष्ट रूप से आधार चुनें: उपयोगकर्ता द्वारा दी गई फ़ाइलों के लिए कार्य निर्देशिका, बंडल संसाधनों के लिए __file__ का मूल, या सेवाओं के लिए एक कॉन्फ़िगर किया गया पूर्ण पथ। __file__ एक वैकल्पिक विशेषता है और कुछ मॉड्यूल के लिए अनसेट हो सकता है, इसलिए इसे getattr से सुरक्षित करें। pathlib के absolute() और resolve() अलग हैं: resolve() '..' को भी हटाता है और symlinks को फॉलो करता है। सभी जगह एक समान डिफ़ॉल्ट नहीं होता; प्रत्येक लॉन्च वातावरण की जाँच करें और कार्य निर्देशिका और हल किया गया पथ दोनों लॉग करें।
कार्य निर्देशिका सापेक्ष पथ को क्यों नियंत्रित करती है
data/config.json जैसा पथ Python द्वारा स्वयं व्याख्या नहीं किया जाता; इसे ऑपरेटिंग सिस्टम को पास किया जाता है, जो इसे प्रक्रिया के वर्तमान कार्य निर्देशिका के सापेक्ष हल करता है। उस निर्देशिका को एक बार सेट किया जाता है जब प्रक्रिया शुरू होती है और यह आपके स्क्रिप्ट का अनुसरण नहीं करती। pathlib.Path.cwd() वर्तमान निर्देशिका का प्रतिनिधित्व करने वाला एक नया पथ ऑब्जेक्ट लौटाता है, जैसा कि os.getcwd() द्वारा लौटाया जाता है। इसलिए वही निर्देशिका एक टर्मिनल में एक परिणाम दे सकती है, IDE में दूसरा, और सेवा मैनेजर के तहत तीसरा। एक missing-file त्रुटि के निदान में पहला कदम स्क्रिप्ट की स्थिति का अनुमान लगाना नहीं, बल्कि रिकॉर्ड करना है कि प्रक्रिया वास्तव में अपनी निर्देशिका के रूप में क्या देखती है।
import os
from pathlib import Path
# 1. जाँचें कि लॉन्चर वास्तव में क्या सेट करता है।
print("cwd:", os.getcwd())
print("cwd path:", Path.cwd())
print("script dir:", Path(__file__).resolve().parent)प्रत्येक लॉन्च संदर्भ के लिए स्पष्ट आधार चुनना
एक बार जब आप कार्य निर्देशिका जान लें, तो निर्णय लें कि आप कौन सा आधार चाहते हैं। उपयोगकर्ता द्वारा दी गई इनपुट के लिए, कार्य निर्देशिका अक्सर सही विकल्प होती है क्योंकि उपयोगकर्ता उम्मीद करते हैं कि पथ उस स्थान के सापेक्ष हों जहाँ से उन्होंने टूल लॉन्च किया। अपने कोड के साथ यात्रा करने वाले बंडल संसाधनों के लिए, पथ को स्क्रिप्ट या पैकेज स्थिति पर आधारित करें। लंबे समय तक चलने वाली सेवाओं के लिए, एक कॉन्फ़िगर किया गया पूर्ण पथ पसंद करें ताकि सेवा समान रूप से व्यवहार करे चाहे प्रक्रिया मैनेजर इसे कैसे शुरू करता हो। फ़ाइल खोलने वाले कोड के पास चुने गए कन्वेंशन को दस्तावेज़ करें, क्योंकि भविष्य के मेंटेनर अन्यथा मानेंगे कि स्क्रिप्ट स्थिति डिफ़ॉल्ट है।
__file__ का सावधानीपूर्वक उपयोग जब यह उपलब्ध हो
मॉड्यूल __file__ विशेषता उस फ़ाइल की ओर इशारा कर सकती है जिसने वर्तमान कोड को परिभाषित किया, जिससे यह बंडल संसाधनों का पता लगाने के लिए उपयोगी बन जाती है। डेटा मॉडल दस्तावेज़ चेतावनी देता है कि __file__ वैकल्पिक है और कुछ मॉड्यूल के लिए अनसेट हो सकता है, जिसमें स्टैटिकली लिंक किए गए C मॉड्यूल या असामान्य स्रोतों से लोड किए गए मॉड्यूल शामिल हैं। getattr से पहुँच को सुरक्षित करें ताकि विशेषता अनुपस्थित होने पर कोड त्रुटि न दे। जब __file__ मौजूद हो, तो सहकर्मी पथ निकालने से पहले इसे एक पूर्ण रूप में हल करें, क्योंकि एक सापेक्ष __file__ अभी भी कार्य निर्देशिका पर निर्भर करेगा।
pathlib में absolute() बनाम resolve()
pathlib पथ को पूर्ण बनाने के दो तरीके प्रदान करता है, और वे आपस में बदलने योग्य नहीं हैं। Path.absolute() पथ को बिना सामान्यीकरण या symlinks हल किए पूर्ण बनाता है, जो os.path.abspath() के करीब है लेकिन सुरक्षा के लिए '..' खंडों को बनाए रखता है। Path.resolve() पथ को पूर्ण बनाता है, '..' घटकों को हटाता है, और symlinks को फॉलो करता है, जो os.path.realpath() के करीब है। यदि आपको किसी मौजूदा फ़ाइल का वास्तविक स्थान चाहिए, तो resolve() आमतौर पर बेहतर विकल्प है। यदि आपको केवल बिना फ़ाइलसिस्टम को छुए एक स्थिर पूर्ण रूप चाहिए, तो absolute() बेहतर हो सकता है।
कार्य निर्देशिका और हल किया गया पथ लॉग करना
जब कोई फ़ाइल नहीं मिलती है, तो कार्य निर्देशिका और उस पथ दोनों लॉग करें जिसे आप खोलने का प्रयास कर रहे थे। वह जोड़ी आमतौर पर स्क्रिप्ट की स्थिति के बारे में अनुमान लगाने से त्रुटि को तेज़ी से समझाती है। जब संभव हो, लॉन्च संदर्भ भी शामिल करें, जैसे कि क्या प्रक्रिया टर्मिनल, IDE रन कॉन्फ़िगरेशन, या सेवा मैनेजर से शुरू की गई थी। यदि पथ कॉन्फ़िगरेशन पर निर्भर करता है, तो कॉन्फ़िगरेशन मान भी लॉग करें। ये रिकॉर्ड बाद में वातावरण को पुनः उत्पन्न करना संभव बनाते हैं बजाय एक सार्वभौमिक डिफ़ॉल्ट की धारणा करने के।
जाँचने के लिए सामान्य लॉन्चर अंतर
टर्मिनल लॉन्च अक्सर शेल की वर्तमान निर्देशिका के साथ शुरू होते हैं, जो प्रोजेक्ट रूट या वह फ़ोल्डर हो सकता है जहाँ आपने cd किया। IDE रन कॉन्फ़िगरेशन कार्य निर्देशिका को प्रोजेक्ट रूट, मॉड्यूल फ़ोल्डर, या लॉन्च सेटिंग्स में परिभाषित एक कस्टम मान पर सेट कर सकते हैं। सेवा मैनेजर और कंटेनर एंट्रypoints प्रक्रिया को एक सिस्टम निर्देशिका या एक घोषित कार्य निर्देशिका में शुरू कर सकते हैं जो कोड स्थिति से अलग होती है। चूंकि ये डिफ़ॉल्ट बदलते हैं, प्रत्येक वातावरण में वास्तविक शुरूआत निर्देशिका का परीक्षण करें बजाय एक मशीन के व्यवहार पर भरोसा करने के।
पथ-संवेदी कोड के लिए व्यावहारिक शुरूआत जाँच
ऐसे अनुप्रयोगों के लिए जो जल्दी फ़ाइलें खोलते हैं, एक छोटी शुरूआत जाँच जोड़ें जो कार्य निर्देशिका और आपके द्वारा उपयोग करने के इरादे वाले आधार पथ को प्रिंट या लॉग करती है। यदि आधार __file__ से आता है, तो जाँचें कि विशेषता मौजूद है और उपयोग से पहले इसे हल करें। यदि आधार कॉन्फ़िगरेशन से आता है, तो पुष्टि करें कि कॉन्फ़िगर किया गया पथ पूर्ण है या दस्तावेज़ करें कि इसे कैसे व्याख्या किया जाएगा। यह जाँच विशेष रूप से स्वचालित वातावरण में उपयोगी है जहाँ लॉन्च निर्देशिका स्रोत कोड से स्पष्ट नहीं होती।
सीमाएँ और संस्करण विचार
यहाँ वर्णित व्यवहार प्रक्रिया कार्य निर्देशिका और यह पर निर्भर करता है कि __file__ सेट है या नहीं, दोनों में Python कार्यान्वयन और लॉन्च वातावरण के पार बदलाव हो सकता है। pathlib का सामान्यीकरण भी यह बदल सकता है कि अन्य उपकरण एक पथ को कैसे व्याख्या करते हैं, इसलिए pathlib हर परिदृश्य में os.path के लिए एक पूर्ण ड्रॉप-इन प्रतिस्थापन नहीं है। कुछ pathlib विधियाँ हाल के Python संस्करणों में बदल गई हैं, जिसमें symlinks लूप और आरक्षित पथों का कठोरतर प्रबंधन शामिल है, इसलिए लक्ष्य रनटाइम पर व्यवहार की जाँच करें। जब पोर्टेबिलिटी मायने रखती है, तो स्पष्ट पूर्ण आधार पसंद करें और इस धारणा से बचें कि सापेक्ष पथ हर जगह समान तरीके से हल होंगे।
क्या जाँचें
- शुरूआत में Path.cwd() या os.getcwd() प्रिंट करें ताकि प्रत्येक लॉन्चर के लिए वास्तविक कार्य निर्देशिका की पुष्टि हो।
- सापेक्ष पथ के लिए स्पष्ट आधार का उपयोग करें: उपयोगकर्ता फ़ाइलों के लिए कार्य निर्देशिका, बंडल संसाधनों के लिए __file__ का मूल, या सेवाओं के लिए एक कॉन्फ़िगर किया गया पूर्ण पथ।
- __file__ को getattr से सुरक्षित करें क्योंकि यह वैकल्पिक है और कुछ मॉड्यूल के लिए अनसेट हो सकता है।
- जब आपको '..' हटाना और symlinks फॉलो करना चाहिए तो pathlib का resolve() चुनें, और जब आपको केवल बिना सामान्यीकरण के एक पूर्ण रूप चाहिए तो absolute() चुनें।
उपयोग की सीमाएँ
सापेक्ष पथ हल कार्य प्रक्रिया कार्य निर्देशिका पर निर्भर करता है, जो टर्मिनल, IDE और सेवा लॉन्च के पार भिन्न होती है। __file__ वैकल्पिक है और कुछ मॉड्यूल के लिए अनुपस्थित हो सकता है। pathlib के absolute() और resolve() अलग व्यवहार करते हैं, और pathlib का सामान्यीकरण यह बदल सकता है कि अन्य उपकरण पथों को कैसे व्याख्या करते हैं। कुछ pathlib व्यवहार हाल के Python संस्करणों में भी बदले हैं, इसलिए लक्ष्य रनटाइम पर जाँच करें।