क्या कोई अजगर के सापेक्ष आयात की व्याख्या कर सकता है?


174

मैं मेरे जीवन के लिए काम करने के लिए अजगर के सापेक्ष आयात नहीं कर सकता। मैंने एक सरल उदाहरण बनाया है जहां यह कार्य नहीं करता है:

निर्देशिका संरचना है:

/__init__.py
/start.py
/parent.py
/sub/__init__.py
/sub/relative.py

/start.py इसमें शामिल हैं: import sub.relative

/sub/relative.py बस होता है from .. import parent

अन्य सभी फाइलें खाली हैं।

कमांड लाइन पर निम्नलिखित निष्पादित करते समय:

$ cd /
$ python start.py

मुझे मिला:

Traceback (most recent call last):
  File "start.py", line 1, in <module>
    import sub.relative
  File "/home/cvondrick/sandbox/sub/relative.py", line 1, in <module>
    from .. import parent
ValueError: Attempted relative import beyond toplevel package

मैं पाइथन 2.6 का उपयोग कर रहा हूं। यह एक केस क्यों है? मैं इस सैंडबॉक्स उदाहरण को कैसे काम करूं?

जवाबों:


140

आप पैकेज "सब" से आयात कर रहे हैं। start.pyएक पैकेज में ही नहीं है, भले ही एक __init__.pyवर्तमान है।

आपको एक से अधिक निर्देशिकाओं से अपना कार्यक्रम शुरू करना होगा parent.py:

./start.py

./pkg/__init__.py
./pkg/parent.py
./pkg/sub/__init__.py
./pkg/sub/relative.py

के साथ start.py:

import pkg.sub.relative

अब pkg शीर्ष स्तर का पैकेज है और आपके रिश्तेदार को आयात करना चाहिए।


यदि आप अपने वर्तमान लेआउट के साथ रहना चाहते हैं तो आप बस उपयोग कर सकते हैं import parent। क्योंकि आप start.pyअपने दुभाषिया को लॉन्च करने के लिए उपयोग करते हैं, जहां start.pyस्थित निर्देशिका आपके अजगर पथ में है। parent.pyएक अलग मॉड्यूल के रूप में रहता है।

आप शीर्ष स्तर को सुरक्षित रूप से हटा सकते हैं __init__.py, यदि आप निर्देशिका ट्री के आगे स्क्रिप्ट में कुछ भी आयात नहीं करते हैं।


2
आप 'मॉड्यूल' और 'पैकेज' शब्दों को भ्रमित कर रहे हैं। 'start.py' मॉड्यूल 'start' का प्रतिनिधित्व करता है, 'mod' और 'mod.sub' पैकेज होते हैं, 'mod' एक अचंभित पैकेज है।
फर्डिनेंड बेयर

34
धन्यवाद, लेकिन यह सच में मूर्खतापूर्ण लगता है। इतनी सुंदर भाषा के लिए, मुझे विश्वास नहीं हो रहा है कि डिजाइनर इस तरह के प्रतिबंध का निर्माण करेंगे। क्या कोई और रास्ता नहीं है?
कारल

2
यह मूर्खतापूर्ण नहीं है। रिलेटिव इंपोर्ट एक पैकेज के भीतर सिबलिंग मॉड्यूल को संदर्भित करने का एक माध्यम है। यदि आप एक पर्याप्त मॉड्यूल आयात करना चाहते हैं, तो पूर्ण आयात का उपयोग करें।
फर्डिनेंड बेयर

58
मूर्ख नहीं है? तो मारपीट में, ".." आपको परेशान नहीं करेगा?
ई-सिटिस

2
यह मुझे लगता है कि अजगर का विचार निर्देशिका से "पूर्ण" आयात का उपयोग करना है जहां आपने अपनी मूल स्क्रिप्ट लॉन्च की थी। तो आप पालक मॉड्यूल को सिबलिंग से आयात करने के लिए पूर्ण पथ "इम्पोर्ट पैरेंट" का उपयोग कर सकते हैं। और रिश्तेदार किसी तरह की विरासत या जो कुछ भी आयात करते हैं ..
ओडीसियस

35

यदि आप relative.pyसीधे कॉल करने जा रहे हैं और यदि आप वास्तव में एक शीर्ष स्तर के मॉड्यूल से आयात करना चाहते हैं, तो आपको स्पष्ट रूप से इसे sys.pathसूची में जोड़ना होगा ।
यहाँ है कि यह कैसे काम करना चाहिए:

# Add this line to the beginning of relative.py file
import sys
sys.path.append('..')

# Now you can do imports from one directory top cause it is in the sys.path
import parent

# And even like this:
from parent import Parent

यदि आपको लगता है कि उपरोक्त किसी प्रकार की असंगति का कारण बन सकता है, तो आप इसके बजाय इसका उपयोग कर सकते हैं:

sys.path.append(sys.path[0] + "/..")

sys.path[0] उस पथ को संदर्भित करता है जिसमें से प्रवेश बिंदु चलाया गया था।


3

Python3 में इसकी जाँच करना:

python -V
Python 3.6.5

उदाहरण 1:

.
├── parent.py
├── start.py
└── sub
    └── relative.py

- start.py
import sub.relative

- parent.py
print('Hello from parent.py')

- sub/relative.py
from .. import parent

यदि हम इसे इस तरह से चलाते हैं (केवल यह सुनिश्चित करने के लिए कि PYTHONPATH खाली है):

PYTHONPATH='' python3 start.py

आउटपुट:

Traceback (most recent call last):
  File "start.py", line 1, in <module>
    import sub.relative
  File "/python-import-examples/so-example-v1/sub/relative.py", line 1, in <module>
    from .. import parent
ValueError: attempted relative import beyond top-level package

अगर हम आयात में परिवर्तन करते हैं sub/relative.py

- sub/relative.py
import parent

अगर हम इसे इस तरह चलाते हैं:

PYTHONPATH='' python3 start.py

आउटपुट:

Hello from parent.py

example2:

.
├── parent.py
└── sub
    ├── relative.py
    └── start.py

- parent.py
print('Hello from parent.py')

- sub/relative.py
print('Hello from relative.py')

- sub/start.py
import relative
from .. import parent

इसे ऐसे चलाएं:

PYTHONPATH='' python3 sub/start.py

आउटपुट:

Hello from relative.py
Traceback (most recent call last):
  File "sub/start.py", line 2, in <module>
    from .. import parent
ValueError: attempted relative import beyond top-level package

यदि हम आयात में परिवर्तन करते हैं sub/start.py:

- sub/start.py
import relative
import parent

इसे ऐसे चलाएं:

PYTHONPATH='' python3 sub/start.py

आउटपुट:

Hello from relative.py
Traceback (most recent call last):
  File "sub/start.py", line 3, in <module>
    import parent
ModuleNotFoundError: No module named 'parent'

इसे ऐसे चलाएं:

PYTHONPATH='.' python3 sub/start.py

आउटपुट:

Hello from relative.py
Hello from parent.py

इसके अलावा रूट फ़ोल्डर से आयात का उपयोग करना बेहतर है, अर्थात:

- sub/start.py
import sub.relative
import parent

इसे ऐसे चलाएं:

PYTHONPATH='.' python3 sub/start.py

आउटपुट:

Hello from relative.py
Hello from parent.py
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.