परिपत्र निर्भरता को समझने के लिए, आपको याद रखना चाहिए कि पायथन अनिवार्य रूप से एक स्क्रिप्टिंग भाषा है। संकलित समय पर बाहर के तरीकों का निष्पादन होता है। इम्पोर्ट स्टेटमेंट को मेथड कॉल की तरह ही निष्पादित किया जाता है, और उन्हें समझने के लिए आपको उनके बारे में सोचना चाहिए जैसे मेथड कॉल।
जब आप एक आयात करते हैं, तो क्या होता है यह निर्भर करता है कि आप जो फ़ाइल आयात कर रहे हैं वह मॉड्यूल तालिका में पहले से मौजूद है। यदि ऐसा होता है, पायथन जो कुछ भी वर्तमान में प्रतीक तालिका में है का उपयोग करता है। यदि नहीं, तो पायथन मॉड्यूल फ़ाइल को पढ़ना शुरू कर देता है, जो कुछ भी वहां मिलता है उसे संकलित / निष्पादित / आयात करता है। संकलित समय पर संदर्भित प्रतीक पाए जाते हैं या नहीं, यह इस बात पर निर्भर करता है कि वे देखे गए हैं, या अभी तक संकलक द्वारा देखे जा सकते हैं।
कल्पना कीजिए कि आपके पास दो स्रोत फाइलें हैं:
फ़ाइल X.py
def X1:
return "x1"
from Y import Y2
def X2:
return "x2"
फ़ाइल Y.py
def Y1:
return "y1"
from X import X1
def Y2:
return "y2"
अब मान लीजिए कि आप फाइल को X.py। संकलक X 1 विधि को परिभाषित करके शुरू होता है, और फिर X.py में आयात कथन को हिट करता है। इसके कारण कंपाइलर X.py का संकलन रोक देता है और Y.py संकलित करना शुरू कर देता है। इसके तुरंत बाद कंपाइलर Y.py में इंपोर्ट स्टेटमेंट को हिट करता है। चूंकि X.py पहले से ही मॉड्यूल तालिका में है, पाइथन अनुरोध किए गए किसी भी संदर्भ को संतुष्ट करने के लिए मौजूदा अपूर्ण X.py प्रतीक तालिका का उपयोग करता है। X.py में इंपोर्ट स्टेटमेंट से पहले दिखाई देने वाला कोई भी सिंबल अब सिंबल टेबल में है, लेकिन उसके बाद का कोई सिंबल नहीं है। चूंकि X1 अब आयात स्टेटमेंट से पहले दिखाई देता है, इसलिए इसे सफलतापूर्वक आयात किया जाता है। पाइथन फिर Y.py का संकलन शुरू करता है। ऐसा करने में यह Y2 को परिभाषित करता है और Y.py को पूरा करता है। इसके बाद X.py का संकलन फिर से शुरू होता है, और Y2 को Y.py प्रतीक तालिका में पाता है। संकलन अंततः w / o त्रुटि पूर्ण करता है।
यदि आप कमांड लाइन से Y.py संकलित करने का प्रयास करते हैं तो कुछ बहुत अलग होता है। Y.py को संकलित करते समय, कंपाइलर Y2 को परिभाषित करने से पहले आयात स्टेटमेंट को हिट करता है। फिर यह X.py का संकलन शुरू करता है। जल्द ही यह X.py में आयात कथन को हिट करता है जिसके लिए Y2 की आवश्यकता होती है। लेकिन Y2 अपरिभाषित है, इसलिए संकलन विफल रहता है।
कृपया ध्यान दें कि यदि आप Y1 को आयात करने के लिए X.py संशोधित करते हैं, तो संकलन हमेशा सफल होगा, चाहे आप जो भी फ़ाइल संकलित करें। हालाँकि यदि आपने प्रतीक X2 को आयात करने के लिए फ़ाइल Y.py संशोधित किया है, तो न तो फ़ाइल संकलित होगी।
किसी भी समय जब मॉड्यूल एक्स, या एक्स द्वारा आयातित कोई मॉड्यूल वर्तमान मॉड्यूल को आयात कर सकता है, तो उपयोग न करें:
from X import Y
किसी भी समय आपको लगता है कि एक परिपत्र आयात हो सकता है आपको अन्य मॉड्यूल में चर के संकलन समय संदर्भों से भी बचना चाहिए। निर्दोष दिखने वाले कोड पर विचार करें:
import X
z = X.Y
मान लें कि इस मॉड्यूल के आयात से पहले मॉड्यूल X इस मॉड्यूल को आयात करता है। इसके अलावा मान लीजिए कि Y आयात आयात विवरण के बाद X में परिभाषित किया गया है। तब वाई को परिभाषित नहीं किया जाएगा जब यह मॉड्यूल आयात किया जाता है, और आपको एक संकलन त्रुटि मिलेगी। यदि यह मॉड्यूल पहले Y आयात करता है, तो आप इसके साथ भाग सकते हैं। लेकिन जब आपका कोई सहकर्मी निर्दोष रूप से परिभाषाओं के क्रम को तीसरे मॉड्यूल में बदलता है, तो कोड टूट जाएगा।
कुछ मामलों में आप अन्य मॉड्यूल द्वारा आवश्यक प्रतीक परिभाषाओं के नीचे एक आयात विवरण को स्थानांतरित करके परिपत्र निर्भरता को हल कर सकते हैं। उपरोक्त उदाहरणों में, आयात कथन से पहले की परिभाषाएँ कभी विफल नहीं होती हैं। संकलन के आदेश के आधार पर आयात विवरण के बाद परिभाषाएँ कभी-कभी विफल हो जाती हैं। आप किसी फ़ाइल के अंत में आयात स्टेटमेंट भी डाल सकते हैं, इसलिए जब तक संकलन समय पर किसी भी आयातित प्रतीकों की आवश्यकता नहीं होती है।
ध्यान दें कि मॉड्यूल में आयात स्टेटमेंट नीचे जाने से आप जो कर रहे हैं वह अस्पष्ट हो जाता है। इसके लिए अपने मॉड्यूल के शीर्ष पर एक टिप्पणी के साथ इसे कुछ इस तरह से लिखें:
#import X (actual import moved down to avoid circular dependency)
सामान्य तौर पर यह एक बुरा अभ्यास है, लेकिन कभी-कभी इससे बचना मुश्किल होता है।