পাইথনের আপেক্ষিক আমদানি কি কেউ ব্যাখ্যা করতে পারেন?


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

আমি পাইথন ২.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

এখন পিকেজি হ'ল শীর্ষ স্তরের প্যাকেজ এবং আপনার আপেক্ষিক আমদানির কাজ করা উচিত।


আপনি যদি আপনার বর্তমান লেআউটটি আটকে রাখতে চান তবে আপনি কেবল ব্যবহার করতে পারেন import parent। যেহেতু আপনি start.pyআপনার দোভাষী চালু করতে ব্যবহার করেন , ডিরেক্টরিটি start.pyআপনার অজগর পথে রয়েছে। parent.pyএকটি পৃথক মডিউল হিসাবে সেখানে বাস।

আপনি আরও __init__.pyযদি ডিরেক্টরি স্ক্রিপ্টে কোনও স্ক্রিপ্টে কিছু আমদানি না করেন তবে আপনি নিরাপদে শীর্ষ স্তরটি মুছে ফেলতে পারেন।


2
আপনি 'মডিউল' এবং 'প্যাকেজ' পদটি বিভ্রান্ত করছেন। 'স্টার্ট.পি' মডিউলটিকে 'স্টার্ট', 'মোড' এবং 'মোড.সুব' প্যাকেজ হিসাবে উপস্থাপন করে, 'মোড' একটি টপলেভ প্যাকেজ।
ফারডিনান্দ বায়ার

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

পাইথন 3 এ এটি পরীক্ষা করা হচ্ছে:

python -V
Python 3.6.5

Example1:

.
├── 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='' 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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.