মূল ফোল্ডার থেকে মডিউলগুলি আমদানি করা হচ্ছে


624

আমি পাইথন 2.5 চালাচ্ছি।

এটি আমার ফোল্ডার ট্রি:

ptdraft/
  nib.py
  simulations/
    life/
      life.py

(আমার __init__.pyপাঠ্যযোগ্যতার জন্য এখানে প্রতিটি ফোল্ডারে বাদ দেওয়া আছে)

আমি nibমডিউলটির ভিতর থেকে কীভাবে আমদানি করব life? আমি আশা করছি যে সিস.পাথের সাথে ঝাঁকুনি না দিয়ে এটি করা সম্ভব।

দ্রষ্টব্য: চলমান মূল মডিউলটি ptdraftফোল্ডারে রয়েছে।


1
আপনার পাইথনপথ সেটিংটি কী?
এস। লট

2
রস: আমি সেখানে তাকিয়ে ছিল। এটি সম্পর্কে আমার কী করা উচিত? আমি ইতিমধ্যে একটি __init__.py। এস.লোট: আমি কীভাবে চেক করতে জানি না ...
রাম রাছুম

4
শেল থেকে প্রতিধ্বনি Y পাইথনপথ; আমদানি sys; পাইথনের মধ্যে থেকে সিস.প্যাথ প্রিন্ট করুন। docs.python.org/tutorial/…
এস। লট

@ ফ্লিপএমসিএফ গুগল একটি বুদবুদ সার্চ ইঞ্জিন, সুতরাং এই ফলাফলটি আপনার পক্ষে যথেষ্ট উচ্চ যে সত্য তা বিবেচ্য নয়। তার চেয়েও গুরুত্বপূর্ণ এটি হ'ল নন-বুদ্বুদযুক্ত সার্চ ইঞ্জিন, ডাকডগোও এটিকে অত্যন্ত উচ্চতর স্থান দেয়।
আর্টঅফ ওয়ারফেয়ার

3
আমি দৃ strongly়ভাবে সমস্ত sys.pathবা PYTHONPATHউত্তরগুলি এড়িয়ে যাওয়া এবং এনপি 8 এর দুর্দান্ত উত্তরটি পরীক্ষা করার পরামর্শ দিচ্ছি । হ্যাঁ, এটি একটি দীর্ঘ পঠিত। হ্যাঁ, এটি অনেকটা কাজের মতো দেখাচ্ছে। তবে এটিই একমাত্র উত্তর যা সমস্যাটি সঠিকভাবে এবং পরিষ্কারভাবে সমাধান করে।
অরণ-ফে

উত্তর:


118

দেখে মনে হচ্ছে যে সমস্যাটি মডিউলটির সাথে কোনও প্যারেন্ট ডিরেক্টরিতে থাকা বা এর মতো কিছু নেই।

ptdraftআপনাকে পাইথোনপথে থাকা ডিরেক্টরিটি যুক্ত করতে হবে

আপনি বলেছিলেন যে এটি import nibআপনার সাথে কাজ করেছে, এর অর্থ সম্ভবত আপনি ptdraftনিজেকে পাইথনপথে যুক্ত করেছেন (এর পিতামাতার নয়)।


15
যদি আপনি প্রচুর প্যাকেজগুলির সাথে পুনরায় ব্যবহারের প্রয়োজন না হয় এমন কাজ করে থাকেন তবে পাইথনপথে সমস্ত কিছু যুক্ত করা ভাল সমাধান নয়।
জেসন চেং

@ জেসন চেং: তাহলে তারা কেন প্যাকেজ ?
ডেভিস হ্যারিং

6
আমার জন্য এই উত্তরটি কার্যকর হয়েছে। তবে এটি আরও সুস্পষ্ট করার জন্য, পদ্ধতিটি import sysতখন এবং তারপরেsys.path.append("..\<parent_folder>")
বিসিজুয়ান

603

আপনি আপেক্ষিক আমদানি (পাইথন> = 2.5) ব্যবহার করতে পারেন:

from ... import nib

(পাইথন 2.5 তে নতুন কী আছে) পিইপি 328: পরম এবং আপেক্ষিক আমদানি

সম্পাদনা : অন্য একটি বিন্দু যুক্ত হয়েছে '' দুটি প্যাকেজ যেতে


177
ValueError: Attempted relative import in non-package
এন্ডোলিথ

18
@endolith: আপনি একটি প্যাকেজের মধ্যে হতে হবে অর্থাত, আপনি একটি থাকতে হবে Init .py ফাইল।
kirbyfan64sos

31
শীর্ষ স্তরের প্যাকেজ ছাড়িয়ে অপেক্ষাকৃত আমদানির চেষ্টা করা হয়েছে
ব্যবহারকারী

291
আরও সুনির্দিষ্ট হতে আপনার একটি __init__.pyফাইল দরকার ।
কারা ডানিজ

17
নীচের উত্তরটিও দেখুন, যেহেতু যোগ __init__.pyকরা আপনার কেবলমাত্র একমাত্র কাজ নয়: স্ট্যাকওভারফ্লো
বেন ফার্মার

286

আপেক্ষিক আমদানি (যেমন হিসাবে from .. import mymodule) কেবল একটি প্যাকেজে কাজ করে। আপনার বর্তমান মডিউলটির মূল ডিরেক্টরিতে থাকা 'মাইমডিউল' আমদানি করতে:

import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir) 

import mymodule

সম্পাদনা : __file__বৈশিষ্ট্যটি সর্বদা দেওয়া হয় না। ব্যবহারের পরিবর্তে os.path.abspath(__file__)আমি এখন উপস্থিত ফাইলের ফাইলের নাম (এবং পথ) পুনরুদ্ধার করতে পরিদর্শন মডিউলটি ব্যবহার করার পরামর্শ দিয়েছি


97
কিছুটা খাটো:sys.path.insert(1, os.path.join(sys.path[0], '..'))
JHolta

8
Ysোকানোর পরিবর্তে sys.path.append () এড়ানোর কোনও কারণ?
টাইলার

2
@ টাইলার - এটি অন্য কোথাও যদি হয় তবে তা বিবেচনা করতে পারে parentdir, তবে যে পথগুলিতে অলরেডি নির্দিষ্ট করা হয়েছে sys.pathসেখানে 'মায়োমডুল' নামটি সহ আরও একটি মডিউল রয়েছে। parentdirতালিকার প্রথম উপাদান হিসাবে সন্নিবেশ করা sys.pathনিশ্চিত করে যে মডিউলটি parentdirপরিবর্তে আমদানি করা হবে।
রেমি

5
@ জেহলতা যদি আপনি প্যাকেজগুলির সাথে কাজ করে না থাকেন তবে আপনারাই সেরা সমাধান।
জনাথন রেইনার্ট

5
@ জেহলতা দুর্দান্ত ধারণা। sys.path.insert(1, os.path.realpath(os.path.pardir))খুব কাজ করে।
স্পিডকোডার

175

ভাইবোন প্যাকেজগুলি থেকে আমদানি সম্পর্কিত প্রশ্নেরও আমি একই ধরণের উত্তর পোস্ট করেছি। আপনি এটি এখানে দেখতে পারেন

সমাধান ছাড়া sys.pathহ্যাক

সারসংক্ষেপ

  • কোডটিকে একটি ফোল্ডারে মুড়ে দিন (যেমন packaged_stuff )
  • setup.pyযেখানে আপনি সেটআপললস সেটআপ ব্যবহার করেন সেখানে স্ক্রিপ্ট তৈরি করুন ()
  • পাইপ প্যাকেজটি সম্পাদনযোগ্য অবস্থায় ইনস্টল করুন pip install -e <myproject_folder>
  • ব্যবহার করে আমদানি করুন from packaged_stuff.modulename import function_name

সেটআপ

আমি প্রশ্নের মত একই ফোল্ডার কাঠামো ধরে নিই

.
└── ptdraft
    ├── __init__.py
    ├── nib.py
    └── simulations
        ├── __init__.py
        └── life
            ├── __init__.py
            └── life.py

আমি .রুট ফোল্ডারটি কল করি এবং আমার ক্ষেত্রে এটি অবস্থিতC:\tmp\test_imports

ধাপ

1) অ্যা setup.py মূল ফোল্ডারে

এর বিষয়বস্তু setup.pyসহজভাবে হতে পারে

from setuptools import setup, find_packages

setup(name='myproject', version='1.0', packages=find_packages())

মূলত "যে কোনও" setup.pyকাজ করবে। এটি কেবলমাত্র একটি ন্যূনতম কাজের উদাহরণ।

2) ভার্চুয়াল পরিবেশ ব্যবহার করুন

আপনি যদি ভার্চুয়াল পরিবেশের সাথে পরিচিত হন, একটি সক্রিয় করুন এবং পরবর্তী পদক্ষেপে যান। ভার্চুয়াল পরিবেশের ব্যবহার করা হয় না একেবারে প্রয়োজনীয়, কিন্তু তারা হবে সত্যিই দীর্ঘ রান আপনাকে সাহায্য (আপনি চেয়ে বেশি 1 প্রকল্পের চলমান আছে ..)। সর্বাধিক প্রাথমিক পদক্ষেপগুলি (রুট ফোল্ডারে চালিত)

  • ভার্চুয়াল env তৈরি করুন
    • python -m venv venv
  • ভার্চুয়াল env সক্রিয় করুন
    • . /venv/bin/activate(লিনাক্স) বা ./venv/Scripts/activate(উইন)

এ সম্পর্কে আরও জানতে, গুগল "পাইথন ভ্যুচুয়ালেনভ টিউটোরিয়াল" বা এর অনুরূপ। আপনার সম্ভবত কখনও তৈরি করা, সক্রিয়করণ এবং নিষ্ক্রিয় করা ছাড়া অন্য কোনও আদেশের প্রয়োজন নেই।

একবার আপনি ভার্চুয়াল পরিবেশ তৈরি এবং সক্রিয় করার পরে, আপনার কনসোলটি বন্ধনীতে ভার্চুয়াল পরিবেশের নাম দেওয়া উচিত

PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>

3) পিপ আপনার প্রকল্প সম্পাদনাযোগ্য স্থানে ইনস্টল করুন

আপনার শীর্ষ স্তরের প্যাকেজটি myprojectব্যবহার করে ইনস্টল করুন pip। কৌশলটি হ'ল ইনস্টলটি করার সময় -eপতাকাটি ব্যবহার করা । এইভাবে এটি সম্পাদনযোগ্য অবস্থায় ইনস্টল করা হবে এবং .py ফাইলগুলিতে করা সমস্ত সম্পাদনা স্বয়ংক্রিয়ভাবে ইনস্টল করা প্যাকেজটিতে অন্তর্ভুক্ত হবে।

রুট ডিরেক্টরিতে, চালান

pip install -e . (বিন্দুটি নোট করুন, এটি "বর্তমান ডিরেক্টরি" হিসাবে দাঁড়িয়েছে)

আপনি এটি ব্যবহার করে ইনস্টল করাও দেখতে পারেন pip freeze

(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
  Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0

4) mainfolderপ্রতিটি আমদানি প্রিপেন্ড করে আমদানি করুন

এই উদাহরণে, mainfolderহবে ptdraft। এটির সুবিধাটি রয়েছে যে আপনি অন্যান্য মডিউল নামের সাথে পাইথন সংঘর্ষে দৌড়াবেন না (পাইথন স্ট্যান্ডার্ড লাইব্রেরি বা তৃতীয় পক্ষের মডিউল থেকে)।


ব্যবহারের উদাহরণ

nib.py

def function_from_nib():
    print('I am the return value from function_from_nib!')

life.py

from ptdraft.nib import function_from_nib

if __name__ == '__main__':
    function_from_nib()

লাইফ.পি চালানো

(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!

1
কেন এই কাজ করে? এটি কি কোনওভাবে পর্দার পিছনে পাইথনপথ পরিবর্তন করছে?
হোমরো

2
এছাড়াও, sys.path পদ্ধতির ব্যবহারের চেয়ে এটি আরও ভাল বা আরও মার্জিত কেন?
হোমরো

5
@ হোমরোবারোকাস এসএসেরাল্ডো ভাল প্রশ্ন। পাইথনপথ এনভ ভার্চ টাচ করা হয়নি। এটি সাইট-প্যাকেজগুলিতে ইনস্টল হয় , যা ইতিমধ্যে চালু আছে sys.pathএবং যেখানে শেষ পর্যন্ত ব্যবহারকারীরা সাধারণত কোড ইনস্টল করবেন। এটি sys.pathহ্যাকের চেয়ে ভাল (এবং আপনি সেই পথের হ্যাকগুলির বিভাগে পাইথনপথ ব্যবহার করে অন্তর্ভুক্ত করতে পারেন) কারণ এর অর্থ বিকাশের কোডটি অন্য ব্যবহারকারীর মতো একই আচরণ করা উচিত। বিপরীতে, পথ পরিবর্তনগুলি ব্যবহার করার সময়, আমদানি বিবৃতিগুলি অন্যভাবে সমাধান করা হবে।
উইম 21

5
এটি এখন পর্যন্ত, আমি সবচেয়ে ভাল সমাধানটি পড়েছি। এটি আপনার বর্তমান ডিরেক্টরিতে একটি লিঙ্ক তৈরি করে তাই কোডের সমস্ত আপডেটগুলি সরাসরি আপনার কার্যকরী ডিরেক্টরিতে প্রতিফলিত হয়। ইভেন্টে আপনাকে এই এন্ট্রিটি মুছতে হবে, ডিম ফাইলটি ম্যানুয়ালি মুছে ফেলুন এবং ডিস্ট-প্যাকেজগুলিতে সহজ-ইনস্টল থেকে এন্ট্রি সরিয়ে ফেলুন (যদি আপনি পিপ ব্যবহার করেন তবে সাইট-প্যাকেজগুলি)।
রক্ষিত কোঠারি

2
অজগর আমদানির মাথাব্যথা কেন আরও জটিল করে তুলছেন? আমাদের একটি সেটআপ ফাইল, ভার্চুয়াল এনভি, পিপ ইনস্টল লিখতে হবে? ঈশ্বর!
এমারসন জু

68

আপনি "মডিউল অনুসন্ধানের পথ" এ ওএস নির্ভর পথ ব্যবহার করতে পারেন যা সিএস.প্যাথ-তালিকাবদ্ধ রয়েছে । সুতরাং আপনি নীচের মত প্যারেন্ট ডিরেক্টরি সহজেই যুক্ত করতে পারেন

import sys
sys.path.insert(0,'..')

আপনি যদি পিতামাতো-পিতামাতার ডিরেক্টরি যুক্ত করতে চান,

sys.path.insert(0,'../..')

এটি অজগর 2 এবং 3 তে কাজ করে।


6
এটি বর্তমান ডিরেক্টরিটির সাথে তুলনামূলক , মূল স্ক্রিপ্টযুক্ত এমনটিও নয়।
ডেভিস হেরিং

57

যদি পাইথনপথে আপনার মডিউল ফোল্ডারটি যুক্ত করা কাজ করে না, আপনি পাইথন ইন্টারপ্রেটার আমদানি করার জন্য মডিউলগুলির সন্ধান করেন সেখানে আপনার প্রোগ্রামের সিএস.পথ তালিকাটি পরিবর্তন করতে পারেন , পাইথন ডকুমেন্টেশন বলে:

স্প্যাম নামের একটি মডিউল আমদানি করা হলে, দোভাষী প্রথমে সেই নামের সাথে অন্তর্নির্মিত মডিউলটি অনুসন্ধান করেন। যদি এটি না পাওয়া যায় তবে এটি ভেরিয়েবল sys.path দ্বারা প্রদত্ত ডিরেক্টরিগুলির তালিকায় স্প্যাম.পি নামের একটি ফাইল অনুসন্ধান করে। sys.path এই অবস্থানগুলি থেকে শুরু করা হয়েছে:

  • ইনপুট স্ক্রিপ্ট (বা বর্তমান ডিরেক্টরি) ধারণকারী ডিরেক্টরি।
  • পাইথনপাথ (শেল ভেরিয়েবল PATH এর মতো একই সিনট্যাক্স সহ ডিরেক্টরি নামের একটি তালিকা)।
  • ইনস্টলেশন নির্ভর ডিফল্ট।

আরম্ভের পরে পাইথন প্রোগ্রামগুলি sys.path পরিবর্তন করতে পারে । স্ক্রিপ্টটি চালু রয়েছে এমন ডিরেক্টরিটি স্ট্যান্ডার্ড লাইব্রেরির পাথের আগে অনুসন্ধানের পথের শুরুতে স্থাপন করা হয়। এর অর্থ এই যে ডিরেক্টরিতে স্ক্রিপ্টগুলি লাইব্রেরি ডিরেক্টরিতে একই নামের মডিউলগুলির পরিবর্তে লোড হবে। প্রতিস্থাপনের উদ্দেশ্যে না হলে এটি একটি ত্রুটি।

এটি জানার পরে, আপনি আপনার প্রোগ্রামে নিম্নলিখিতগুলি করতে পারেন:

import sys
# Add the ptdraft folder path to the sys.path list
sys.path.append('/path/to/ptdraft/')

# Now you can import your module
from ptdraft import nib
# Or just
import ptdraft

6
আপনার উত্তরটি ভাল, তবে সর্বদা চলতে পারে না এবং খুব পোর্টেবল হয় না। প্রোগ্রামটি যদি কোনও নতুন স্থানে স্থানান্তরিত /path/to/ptdraftহয় তবে সম্পাদনা করতে হবে। সমাধান রয়েছে যা ফাইলটির বর্তমান ডিরেক্টরিটি কার্যকর করে এবং প্যারেন্ট ফোল্ডার থেকে সেভাবে আমদানি করে।
এডওয়ার্ড

@ অ্যাডওয়ার্ড এই কৌশলগুলি কি?
শুক্লসওয়াগ

1
উদাহরণস্বরূপ @ শুক্লাসওয়াগ, উত্তর stackoverflow.com/questions/714063/…
এডওয়ার্ড

50

পাইথন ২ সম্পর্কে খুব বেশি কিছু জানেন না p
পাইথন 3-তে, নীচে প্যারেন্ট ফোল্ডারটি যুক্ত করা যেতে পারে:

import sys 
sys.path.append('..')

... এবং তারপরে একজন এটি থেকে মডিউল আমদানি করতে সক্ষম


13
এটি কেবল তখনই কাজ করে যদি আপনার বর্তমান ভার্চিং ডিরেক্টরিটি এমন হয় যা '..'প্রশ্নোক্ত মডিউলটির সাথে ডিরেক্টরিতে পরিচালিত করে।
ব্যবহারকারী5359531

31

এটি একটি সহজ উত্তর যা এখানে আপনি কীভাবে কাজ করেন তা দেখতে পারেন ছোট এবং ক্রস প্ল্যাটফর্ম।
এটা শুধুমাত্র বিল্ট-ইন ব্যবহার মডিউল ( os, sysএবং inspect) যাতে কাজ করা উচিত
কোন অপারেটিং সিস্টেম (ওএস) কারণ পাইথন যে জন্য ডিজাইন করা হয়েছে হয়েছে।

উত্তরের জন্য সংক্ষিপ্ত কোড - কম লাইন এবং ভেরিয়েবল

from inspect import getsourcefile
import os.path as path, sys
current_dir = path.dirname(path.abspath(getsourcefile(lambda:0)))
sys.path.insert(0, current_dir[:current_dir.rfind(path.sep)])
import my_module  # Replace "my_module" here with the module name.
sys.path.pop(0)

এর চেয়ে কম লাইনের জন্য, দ্বিতীয় লাইনটি এর সাথে প্রতিস্থাপন করুন import os.path as path, sys, inspect ,
যোগ inspect.শুরুতে getsourcefile(লাইন 3) এবং প্রথম লাইন মুছে ফেলুন।
- তবে এটি সমস্ত মডিউল আমদানি করে তাই আরও সময়, মেমরি এবং সংস্থান প্রয়োজন হতে পারে।

আমার উত্তরের কোড ( দীর্ঘতর সংস্করণ )

from inspect import getsourcefile
import os.path
import sys

current_path = os.path.abspath(getsourcefile(lambda:0))
current_dir = os.path.dirname(current_path)
parent_dir = current_dir[:current_dir.rfind(os.path.sep)]

sys.path.insert(0, parent_dir)

import my_module  # Replace "my_module" here with the module name.

এটি স্ট্যাক ওভারফ্লো উত্তর থেকে একটি উদাহরণ ব্যবহার করে আমি
পাইথনের বর্তমান সম্পাদিত ফাইলের পথ কীভাবে পাব ?
অন্তর্নির্মিত সরঞ্জাম সহ চলমান কোডের উত্স (ফাইলের নাম) সন্ধান করতে।

from inspect import getsourcefile  
from os.path import abspath  

এর পরে, আপনি যেখান থেকে উত্স ফাইলটি সন্ধান করতে চান সেখানে কেবল ব্যবহার করুন:

abspath(getsourcefile(lambda:0))

আমার কোড এতে একটি ফাইল পাথ যুক্ত করে sys.path , পাইথন পাথ তালিকা
কারণ এই যে ফোল্ডার থেকে আমদানি মডিউল থেকে পাইথন পারেন।

কোডটিতে একটি মডিউল আমদানি করার পরে, sys.path.pop(0)নতুন লাইনে চালানো ভাল ধারণা
যখন যুক্ত ফোল্ডারে অন্য নামের সাথে মডিউল থাকে যা অন্য মডিউল হিসাবে আমদানি করা হয়
প্রোগ্রামের পরে । আপনার আমদানির আগে যুক্ত তালিকা আইটেমটি অপসারণ করতে হবে, অন্য পাথ নয়।
যদি আপনার প্রোগ্রামটি অন্য মডিউলগুলি আমদানি না করে তবে ফাইলের পাথটি মুছে ফেলা নিরাপদ কারণ
কোনও প্রোগ্রাম শেষ হওয়ার পরে (বা পাইথন শেলটি পুনরায় চালু করার পরে) যে কোনও সম্পাদনা sys.pathঅদৃশ্য হয়ে যাবে।

একটি ফাইলের নাম ভেরিয়েবল সম্পর্কে নোট

আমার উত্তরটি __file__চলমান
কোডের ফাইলের পাথ / ফাইল নাম পেতে ভেরিয়েবলটি ব্যবহার করে না কারণ এখানে ব্যবহারকারীরা প্রায়শই এটি অবিশ্বস্ত হিসাবে বর্ণনা করেছেন । অন্যান্য ব্যক্তিদের দ্বারা ব্যবহৃত প্রোগ্রামগুলিতে প্যারেন্ট ফোল্ডার থেকে মডিউলগুলি আমদানির
জন্য আপনার ব্যবহার করা উচিত নয় ।

কিছু উদাহরণ যেখানে এটি কাজ করে না ( এই স্ট্যাক ওভারফ্লো প্রশ্ন থেকে উদ্ধৃতি ):

• এটা করা যাবে না কিছু প্ল্যাটফর্মের • কখনও কখনও পাওয়া পূর্ণ ফাইল পাথ নয়

  • py2exe একটি নেই __file__ গুণ, কিন্তু একটি কার্যসংক্রান্ত নেই
  • আপনি যখন আইডিএল থেকে চালাবেন তখন execute()কোনও নেই__file__ বৈশিষ্ট্য নেই
  • ওএস এক্স 10.6 যেখানে আমি পাই NameError: global name '__file__' is not defined

1
আমি এটি করেছি sys.path.pop(0)এবং পছন্দসই মডিউলটি আমদানি করার সাথে সাথেই নতুন পাথ এন্ট্রি সরিয়ে ফেললাম । যাইহোক, পরবর্তী আমদানিগুলি এখনও সেই জায়গায় গিয়েছিল। উদাহরণস্বরূপ, আমার আছে app/config, app/toolsএবং app/submodule/config। থেকে submodule, আমি app/আমদানিতে সন্নিবেশ করি tools, তারপরে সরান app/এবং আমদানির চেষ্টা configকরি, তবে আমি এর app/configপরিবর্তে পাই app/submodule/config
ব্যবহারকারীর 35359531

আমি বুঝতে পেরেছি যে এর একটি toolsআমদানি configপিতা বা মাতা থেকেও আমদানি করছিল । সুতরাং পরে যখন আমি sys.path.pop(0); import configভিতরে করার চেষ্টা করলাম submodule, প্রত্যাশা app/submodule/configকরছিলাম, আমি আসলে পেয়ে যাচ্ছিলাম app/config। স্পষ্টতই পাইথন সেই নামটির সাথে sys.pathমিলে যাওয়া মডিউলের জন্য পরীক্ষার পরিবর্তে একই নামে একটি মডিউলের ক্যাশেড সংস্করণ দেয় । sys.pathএই ক্ষেত্রে সঠিকভাবে পরিবর্তন করা হচ্ছে, একই নামযুক্ত মডিউলটি ইতিমধ্যে লোড হওয়ার কারণে পাইথন কেবল এটি পরীক্ষা করছে না।
ব্যবহারকারী5359531

আমার মনে হয় এটি আমার যে ইস্যুটি ছিল তার সঠিক রেফারেন্স: ডকস.পিথথন.অর্গ
/

5.3.1 থেকে কিছু দরকারী তথ্য মডিউল ক্যাশে উপর ডকুমেন্টেশন পৃষ্ঠাটিতে : আমদানি করার সময়, মডিউল নামে তাকিয়ে করা হয় sys.modules ... sys.modules লিখনযোগ্য নয়। একটি কী মুছে ফেলা নামকৃত মডিউলটির জন্য ক্যাশে প্রবেশকে অবৈধ করে দেবে, যার ফলে পাইথন তার পরবর্তী আমদানিতে নতুনভাবে অনুসন্ধান করবে। ... সতর্কতা অবলম্বন করুন, আপনি যদি মডিউল অবজেক্টের কোনও রেফারেন্স রাখেন তবে এর ক্যাশেটি অবৈধ করুন পুনরায় আমদানি করুন, দুটি অবজেক্ট আলাদা হবে। বিপরীতে, importlib.reload()মডিউল বিষয়বস্তু পুনরায় ব্যবহার এবং পুনরায় পুনর্নির্মাণ করা হবে ...
এডওয়ার্ড

এমনকি খাটো: os.path.realpath(getsourcefile(lambda:0) + "/../..")। দুটি উত্স ডিরেক্টরি চিহ্নের সাথে সংযুক্ত বর্তমান উত্স ফাইলটি পাবেন। আমি ব্যবহার করা হয়নি os.path.sepযেমন getsourcefileআয় ছিল ব্যবহার করে একটি স্ট্রিং /এমনকি Windows এ। realpathসম্পূর্ণ পথ থেকে দুটি ডিরেক্টরি এন্ট্রি পপিংয়ের যত্ন নেবে (এই ক্ষেত্রে ফাইল নাম এবং তারপরে বর্তমান ডিরেক্টরি) যা প্যারেন্ট ডিরেক্টরিটি দেয়।
কোবার্ন

28

এখানে আরও জেনেরিক সমাধান যা পিতামাতাকে ডিরেক্টরিতে sys.path- এ অন্তর্ভুক্ত করে (আমার জন্য কাজ করে):

import os.path, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))

import os, sys\n sys.path.insert(0,os.path.pardir) একই জিনিস, তবে বাছাই :) (কোনও লাইনে কোনও মন্তব্য নেই)
এন্টি ভিরনা

@ অ্যান্টিভেরান্না, আপনি যদি ব্যবহার করেন তবে আপনি os.path.pardirপিতামাতার রিয়েলপথ পাবেন না, কেবল আপেক্ষিক পথ যেখানে আপনি ফোন করছেনsys.path.insert()
আলওয়াস

1
এই উত্তরটি __file__চলকটি ব্যবহার করে যা অবিশ্বাস্য হতে পারে (সর্বদা সম্পূর্ণ ফাইল পাথ নয়, প্রতিটি অপারেটিং সিস্টেমের উপর কাজ করে না ইত্যাদি) স্ট্যাকওভারফ্লো ব্যবহারকারীরা প্রায়শই উল্লেখ করেছেন। এটি অন্তর্ভুক্ত না করার জন্য উত্তর পরিবর্তন করা কম সমস্যা সৃষ্টি করবে এবং আরও ক্রস-সামঞ্জস্যপূর্ণ হবে। আরও তথ্যের জন্য, stackoverflow.com/a/33532002/3787376 দেখুন
এডওয়ার্ড

22

আমি নীচের উপায়ে স্ক্রিপ্টের মূল ডিরেক্টরি থেকে প্যাকেজ আমদানির জন্য কাজ করে দেখলাম। উদাহরণস্বরূপ, আমি প্যাকেজ env.pyথেকে ফাংশন আমদানি করতে চাই app.db

.
└── my_application
    └── alembic
        └── env.py
    └── app
        ├── __init__.py
        └── db
import os
import sys
currentdir = os.path.dirname(os.path.realpath(__file__))
parentdir = os.path.dirname(currentdir)
sys.path.append(parentdir)

সুতরাং, একটি দুর্দান্ত ওয়ান-লাইনার:sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
জাজলিন

sys.pathমোটেও সংশোধন করা একটি খারাপ ধারণা। আপনার লাইব্রেরিটি অন্যান্য কোডে অ্যাক্সেসযোগ্য হওয়ার জন্য আপনাকে কিছু উপায় ( যেমন , PYTHONPATH) দরকার ; শুধু যে সব সময় ব্যবহার!
ডেভিস হেরিং

14

উপরে উল্লিখিত সমাধানগুলিও ঠিক আছে। এই সমস্যার আর একটি সমাধান হ'ল

আপনি যদি শীর্ষ স্তরের ডিরেক্টরি থেকে কিছু আমদানি করতে চান। তারপর,

from ...module_name import *

এছাড়াও, আপনি যদি প্যারেন্ট ডিরেক্টরি থেকে কোনও মডিউল আমদানি করতে চান। তারপর,

from ..module_name import *

এছাড়াও, আপনি যদি প্যারেন্ট ডিরেক্টরি থেকে কোনও মডিউল আমদানি করতে চান। তারপর,

from ...module_name.another_module import *

আপনি চাইলে যে কোনও বিশেষ পদ্ধতি আমদানি করতে পারেন।


6
এটি যেমনটি হওয়া উচিত ঠিক তেমন মনে হয় তবে কোনও কারণে এটি sys.path.appendউপরের হ্যাকগুলির মতো একইভাবে কাজ করে না এবং আমি আমার লিবটি এর মতো আমদানি করতে পারি না। গুগল শুরু করার আগে এটিই আমি প্রথমে করার চেষ্টা করেছি :) ঠিক আছে, এটি ছিলValueError: attempted relative import beyond top-level package
জাজলিন

10

প্যারেন্ট ডিরেক্টরিতে অ্যাক্সেসের জন্য আমার পক্ষে সবচেয়ে সংক্ষিপ্ততম এবং আমার প্রিয় অনেলাইনার হ'ল:

sys.path.append(os.path.dirname(os.getcwd()))

বা:

sys.path.insert(1, os.path.dirname(os.getcwd()))

os.getcwd () বর্তমান চলমান ডিরেক্টরি ডিরেক্টরিটির নাম দেয়, os.path.dirname (ডিরেক্টরি_নাম) পাস হওয়াটির জন্য ডিরেক্টরিটির নাম প্রদান করে।

আসলে, আমার মতে পাইথন প্রকল্পের আর্কিটেকচারটি এমনভাবে করা উচিত যেখানে শিশু ডিরেক্টরি থেকে কোনও মডিউল প্যারেন্ট ডিরেক্টরি থেকে কোনও মডিউল ব্যবহার করবে না will যদি এরকম কিছু ঘটে থাকে তবে প্রকল্প গাছ সম্পর্কে পুনর্বিবেচনা করা উচিত।

আর একটি উপায় হ'ল পাইথনপথ সিস্টেম এনভায়রনমেন্ট ভেরিয়েবলের সাথে প্যারেন্ট ডিরেক্টরী যুক্ত করা।


2
প্রকল্পটির পুনর্গঠন করার সম্ভাবনাটি উল্লেখ করার জন্য +1 (সমস্যাটিতে একটি হ্যাক নিক্ষেপের বিপরীতে)
semore_1267

এটি পিতামাতাকে পায় না, এটি বর্তমানটি পায়
রিকি লেভি

9

একটি বৃহত্তর নোটবুক

যতক্ষণ আপনি একটি বৃহত্তর নোটবুকে কাজ করছেন, এই সংক্ষিপ্ত সমাধানটি কার্যকর হতে পারে:

%cd ..
import nib

এটি কোনও __init__.pyফাইল ছাড়াই কাজ করে ।

আমি এটি লিনাক্স এবং উইন্ডোজ 7 এ অ্যানাকোন্ডা 3 দিয়ে পরীক্ষা করেছি।


2
%cd -আমদানির পরে যোগ করার অর্থ কী হবে না তাই নোটবুকের বর্তমান ডিরেক্টরিটি অপরিবর্তিত রয়েছে।
Dror


5

যখন প্যাকেজ পরিবেশে না থাকে __init__.pyফাইলগুলির অবস্থায় পাথলিব লাইব্রেরি (>> পাইথন ৩.৪ সহ অন্তর্ভুক্ত) পিতৃপথের জন্য প্যারেন্ট ডিরেক্টরিটির পথ সংযোজন অত্যন্ত সংক্ষিপ্ত এবং স্বজ্ঞাত করে তুলেছে:

import sys
from pathlib import Path
sys.path.append(str(Path('.').absolute().parent))

এই সমস্যাটি থেকে মুক্ত করার জন্য কি init .py ব্যবহার করা সম্ভব ?
কৃত্রিমভাবে উদ্বেগ

4

অতীত উত্তর হিসাবে একই ধরণের শৈলী - তবে কম লাইনে: পি

import os,sys
parentdir = os.path.dirname(__file__)
sys.path.insert(0,parentdir)

ফাইল আপনি যে অবস্থানটিতে কাজ করছেন তা ফিরিয়ে দেয়


আমার জন্য ফাইল ফাইলের নাম হল ছাড়া পথ ছিল। আমি "আইপি ফাইল নাম.পি" ব্যবহার করে এটি চালাচ্ছি।
কার্টিস ইয়ালাপ

হাই @ কার্টিসওয়ালাপ উপরে বর্ণিত উদাহরণে আমরা পাইথন ফাইলটি [যেটিতে আমরা বর্তমানে রয়েছি] যে ডাইর যুক্ত করছি সেটিকে যুক্ত করছি the সেই পথে যা যুক্ত করা হচ্ছে এবং ফাইলটি স্পষ্টভাবে নয়
এইচটিএইচ

আপনি ধরে নিচ্ছেন যে __file__ এ সর্বদা পথ প্লাস ফাইল থাকে। কখনও কখনও এটিতে পথ ছাড়াই কেবল ফাইলের নাম থাকে।
কার্টিস ইয়ালাপ

@ কার্টিসওয়ালাপ - মোটেও স্যার নয়, আমি ধরে নিচ্ছি যে ফাইলটি ফাইলের নাম এবং আমি ফাইলটির পথ পেতে os.path.dirname () ব্যবহার করছি। আপনি কি কাজ না করে এর উদাহরণ পেয়েছেন? আমি পুনরুত্পাদন করার পদক্ষেপগুলি পছন্দ করব
ওয়াইএফপি

1
পুনঃটুইট আমি বলছি: মুদ্রণ / _ / ফাইল / _ / আপনার "ফাইল.পি" উপরের উদাহরণে ফাইলের নাম দেবে - আমি তখন বলছি যে আপনি ওস.পাথ.ডায়ারনাম () ব্যবহার করে পুরো পথটি টানতে পারেন । যদি আপনি কোনও অদ্ভুত অবস্থান থেকে কল করছেন এবং আপনি সেই সম্পর্কটি চান তবে আপনি খুব সহজেই ওএস মডিউলটির মাধ্যমে আপনার কর্মরত দিরকে খুঁজে পেতে পারেন - জিৎ!
YFP

1

লাইব্রেরি দিয়ে কাজ। নিব নামে একটি লাইব্রেরি তৈরি করুন, সেটআপ.পি ব্যবহার করে এটি ইনস্টল করুন, এটি সাইট-প্যাকেজগুলিতে থাকতে দিন এবং আপনার সমস্যাগুলি সমাধান করা হবে। আপনি একক প্যাকেজে যা কিছু করেন তা আপনার স্টাফ করতে হবে না। টুকরো টুকরো করে ফেলুন।


1
আপনার ধারণাটি ভাল তবে কিছু লোক তাদের কোড সহ তাদের মডিউলটি বান্ডিল করতে চাইতে পারে - সম্ভবত এটিকে পোর্টেবল করার জন্য এবং site-packagesপ্রতিটি বার যখন তারা এটি অন্য কোনও কম্পিউটারে চালায় তখন তাদের মডিউলগুলি লাগাতে হবে না ।
এডওয়ার্ড 21

0

একটি লিনাক্স সিস্টেমে আপনি "লাইফ" ফোল্ডার থেকে nib.py ফাইলে একটি নরম লিঙ্ক তৈরি করতে পারেন। তারপরে, আপনি এটিকে সহজভাবে আমদানি করতে পারেন:

import nib
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.