स्क्रिप्ट बनाम मॉड्यूल
यहाँ एक स्पष्टीकरण है। संक्षिप्त संस्करण यह है कि पायथन फ़ाइल को सीधे चलाने और उस फ़ाइल को कहीं और से आयात करने के बीच एक बड़ा अंतर है। बस यह जानना कि कोई फ़ाइल किस डाइरेक्टरी में है, यह निर्धारित नहीं करता है कि पायथन किस पैकेज में है। यह निर्भर करता है, इसके अलावा, आप फ़ाइल को पायथन में कैसे लोड करते हैं (रन करके या आयात करके)।
पायथन फ़ाइल को लोड करने के दो तरीके हैं: शीर्ष-स्तरीय स्क्रिप्ट के रूप में, या एक मॉड्यूल के रूप में। एक फ़ाइल को शीर्ष-स्तरीय स्क्रिप्ट के रूप में लोड किया जाता है यदि आप इसे सीधे निष्पादित करते हैं, उदाहरण के python myfile.py
लिए कमांड लाइन पर टाइप करके । यह एक मॉड्यूल के रूप में लोड किया जाता है यदि आप करते हैं python -m myfile
, या यदि import
किसी अन्य फ़ाइल के अंदर एक बयान का सामना करने पर इसे लोड किया जाता है। एक समय में केवल एक शीर्ष-स्तरीय स्क्रिप्ट हो सकती है; शीर्ष-स्तरीय स्क्रिप्ट पायथन फ़ाइल है जिसे आप चीजों को शुरू करने के लिए चलाते थे।
नामकरण
जब कोई फ़ाइल लोड की जाती है, तो उसे एक नाम दिया जाता है (जो इसकी __name__
विशेषता में संग्रहीत होता है )। यदि इसे शीर्ष-स्तरीय स्क्रिप्ट के रूप में लोड किया गया था, तो इसका नाम है __main__
। यदि इसे एक मॉड्यूल के रूप में लोड किया गया था, तो इसका नाम फ़ाइल नाम है, जो किसी भी पैकेज / सबपैकेज के नामों से पहले है, यह एक हिस्सा है, जिसे डॉट्स द्वारा अलग किया गया है।
उदाहरण के लिए आपके उदाहरण में:
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleA.py
यदि आप आयात करते हैं moduleX
(नोट: आयातित , सीधे निष्पादित नहीं), तो इसका नाम होगा package.subpackage1.moduleX
। यदि आप आयात करते हैं moduleA
, तो इसका नाम होगा package.moduleA
। हालाँकि, यदि आप सीधे moduleX
कमांड लाइन से चलते हैं , तो इसका नाम बदले में होगा __main__
, और यदि आप सीधे moduleA
कमांड लाइन से चलते हैं , तो इसका नाम होगा __main__
। जब एक मॉड्यूल को शीर्ष-स्तरीय स्क्रिप्ट के रूप में चलाया जाता है, तो यह अपना सामान्य नाम खो देता है और इसके बजाय इसका नाम होता है __main__
।
अपने पैकेज युक्त मॉड्यूल के माध्यम से प्रवेश नहीं
एक अतिरिक्त शिकन है: मॉड्यूल का नाम इस बात पर निर्भर करता है कि इसे उस निर्देशिका से "सीधे" आयात किया गया था या पैकेज के माध्यम से आयात किया गया था। इससे केवल तभी फर्क पड़ता है जब आप किसी निर्देशिका में पायथन चलाते हैं, और उसी निर्देशिका में फ़ाइल आयात करने की कोशिश करते हैं (या इसका एक उपनिर्देशिका)। उदाहरण के लिए, यदि आप निर्देशिका में पायथन दुभाषिया शुरू करते हैं package/subpackage1
और फिर करते हैं import moduleX
, तो moduleX
सिर्फ नाम का नाम होगा moduleX
, और नहीं package.subpackage1.moduleX
। ऐसा इसलिए है क्योंकि पायथन वर्तमान निर्देशिका को स्टार्टअप पर अपने खोज पथ में जोड़ता है; यदि यह वर्तमान निर्देशिका में इन-टू-इम्पोर्टेड मॉड्यूल पाता है, तो यह नहीं पता होगा कि वह निर्देशिका पैकेज का हिस्सा है, और पैकेज जानकारी मॉड्यूल के नाम का हिस्सा नहीं बनेगी।
एक विशेष मामला यह है कि यदि आप इंटरप्रेटर को अंतःक्रियात्मक रूप से चलाते हैं (जैसे, बस टाइप करें python
और मक्खी पर पायथन कोड दर्ज करना शुरू करें)। इस मामले में उस संवादात्मक सत्र का नाम है __main__
।
अब यहां आपके त्रुटि संदेश के लिए महत्वपूर्ण बात है: यदि किसी मॉड्यूल के नाम में डॉट्स नहीं हैं, तो इसे पैकेज का हिस्सा नहीं माना जाता है । इससे कोई फर्क नहीं पड़ता कि फ़ाइल वास्तव में डिस्क पर कहां है। यह सब मायने रखता है कि इसका नाम क्या है, और इसका नाम इस बात पर निर्भर करता है कि आपने इसे कैसे लोड किया है।
अब आप अपने प्रश्न में शामिल उद्धरण को देखें:
पैकेज पदानुक्रम में उस मॉड्यूल की स्थिति निर्धारित करने के लिए सापेक्ष आयात एक मॉड्यूल नाम विशेषता का उपयोग करते हैं। यदि मॉड्यूल के नाम में कोई पैकेज जानकारी नहीं है (जैसे कि यह 'मुख्य' पर सेट है) तो सापेक्ष आयात को हल किया जाता है जैसे कि मॉड्यूल एक शीर्ष स्तर मॉड्यूल था, चाहे मॉड्यूल वास्तव में फ़ाइल सिस्टम पर स्थित हो।
सापेक्ष आयात ...
सापेक्ष आयात मॉड्यूल के नाम का उपयोग यह निर्धारित करने के लिए करता है कि यह पैकेज में कहां है। जब आप किसी सापेक्ष आयात का उपयोग करते हैं from .. import foo
, तो डॉट्स पैकेज पदानुक्रम में कुछ स्तरों को बढ़ाने का संकेत देते हैं। उदाहरण के लिए, यदि आपके वर्तमान मॉड्यूल का नाम है package.subpackage1.moduleX
, तो ..moduleA
इसका मतलब होगा package.moduleA
। एक के लिए from .. import
काम करने के लिए, मॉड्यूल के नाम के रूप में वहाँ में हैं कई बिंदुओं के रूप में कम से कम होनी चाहिए import
बयान।
... केवल एक पैकेज में रिश्तेदार हैं
हालांकि, यदि आपके मॉड्यूल का नाम है __main__
, तो इसे पैकेज में नहीं माना जाता है। इसके नाम में कोई बिंदु नहीं है, और इसलिए आप from .. import
इसके अंदर कथनों का उपयोग नहीं कर सकते । यदि आप ऐसा करने की कोशिश करते हैं, तो आपको "गैर-पैकेज में रिश्तेदार-आयात" त्रुटि मिलेगी।
लिपियां सापेक्ष आयात नहीं कर सकती हैं
आपने शायद जो किया था, moduleX
उसे कमांड लाइन से चलाने या पसंद करने की कोशिश की गई है । जब आपने ऐसा किया था, तो इसका नाम सेट किया गया था __main__
, जिसका अर्थ है कि इसके भीतर सापेक्ष आयात विफल हो जाएगा, क्योंकि इसका नाम प्रकट नहीं करता है कि यह एक पैकेज में है। ध्यान दें कि यह तब भी होगा जब आप उसी निर्देशिका से पायथन चलाते हैं जहां एक मॉड्यूल है, और फिर उस मॉड्यूल को आयात करने का प्रयास करें, क्योंकि, जैसा कि ऊपर वर्णित है, पायथन को मौजूदा निर्देशिका में मॉड्यूल को "बहुत जल्दी" पता चलेगा, बिना यह एहसास किए एक पैकेज का हिस्सा।
यह भी याद रखें कि जब आप इंटरैक्टिव दुभाषिया चलाते हैं, तो उस इंटरैक्टिव सत्र का "नाम" हमेशा होता है __main__
। इस प्रकार आप एक इंटरैक्टिव सत्र से सीधे सापेक्ष आयात नहीं कर सकते । सापेक्ष आयात केवल मॉड्यूल फ़ाइलों के भीतर उपयोग के लिए हैं।
दो समाधान:
यदि आप वास्तव में moduleX
सीधे भागना चाहते हैं, लेकिन आप अभी भी चाहते हैं कि इसे एक पैकेज का हिस्सा माना जाए, तो आप कर सकते हैं python -m package.subpackage1.moduleX
। -m
अजगर बताता नहीं उच्च-स्तरीय स्क्रिप्ट के रूप में, एक मॉड्यूल के रूप में यह लोड करने के लिए।
या शायद आप वास्तव में चलाना नहीं चाहते हैंmoduleX
, आप बस कुछ अन्य स्क्रिप्ट को चलाना चाहते हैं, कहते हैं myfile.py
, कि अंदर कार्यों का उपयोग करता है moduleX
। अगर ऐसा है, तो myfile.py
कहीं और डालें - निर्देशिका के अंदर नहींpackage
- और इसे चलाएं। अगर आप अंदर की myfile.py
चीजों को पसंद करते हैं from package.moduleA import spam
, तो यह ठीक काम करेगा।
टिप्पणियाँ
या तो इन समाधानों के लिए, पैकेज निर्देशिका ( package
आपके उदाहरण में) पायथन मॉड्यूल खोज पथ ( sys.path
) से सुलभ होनी चाहिए । यदि यह नहीं है, तो आप पैकेज में किसी भी चीज़ का उपयोग मज़बूती से नहीं कर पाएंगे।
पायथन 2.6 के बाद से, पैकेज-रिज़ॉल्यूशन उद्देश्यों के लिए मॉड्यूल का "नाम" न केवल इसकी __name__
विशेषताओं से निर्धारित होता है, बल्कि विशेषता द्वारा भी __package__
। इसलिए मैं __name__
मॉड्यूल के "नाम" का उल्लेख करने के लिए स्पष्ट प्रतीक का उपयोग करने से बच रहा हूं । चूंकि पायथन 2.6 एक मॉड्यूल का "नाम" प्रभावी रूप से है __package__ + '.' + __name__
, या बस __name__
अगर __package__
है None
।)