স্ক্রিপ্ট বনাম মডিউল
এখানে একটি ব্যাখ্যা। সংক্ষিপ্ত সংস্করণটি হ'ল সরাসরি পাইথন ফাইল চালানো এবং অন্য কোথাও থেকে ফাইলটি আমদানির মধ্যে একটি বড় পার্থক্য রয়েছে। কোন ফাইলটি কোন ডিরেক্টরিতে রয়েছে তা জেনে যাওয়া পাইথন কোন প্যাকেজটিকে প্যাকেজ বলে মনে করে তা নির্ধারণ করে না That এটি নির্ভর করে যে আপনি কীভাবে পাইথনে ফাইলটি লোড করবেন (চালিয়ে বা আমদানির মাধ্যমে)।
পাইথন ফাইল লোড করার দুটি উপায় রয়েছে: শীর্ষ স্তরের স্ক্রিপ্ট হিসাবে বা মডিউল হিসাবে। আপনি যদি সরাসরি এটি প্রয়োগ করেন তবে একটি ফাইল শীর্ষ স্তরের স্ক্রিপ্ট হিসাবে লোড করা হয়, উদাহরণস্বরূপ 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__
, যার অর্থ এটির মধ্যে আপেক্ষিক আমদানি ব্যর্থ হবে, কারণ এর নামটি এটি প্রকাশ করে না যে এটি কোনও প্যাকেজে রয়েছে। নোট করুন যে আপনি যদি মডিউল যেখানে একই ডিরেক্টরি থেকে পাইথন চালনা করেন এবং তারপর সেই মডিউলটি আমদানির চেষ্টা করেন, কারণ উপরে বর্ণিত হিসাবে পাইথন বর্তমান ডিরেক্টরিটিতে মডিউলটি উপলব্ধি না করে "খুব তাড়াতাড়ি" খুঁজে পাবেন is একটি প্যাকেজের অংশ।
এছাড়াও মনে রাখবেন যে আপনি যখন ইন্টারেক্টিভ দোভাষীটি চালাবেন, সেই ইন্টারেক্টিভ সেশনের "নাম" সর্বদা থাকে __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
) থেকে অ্যাক্সেসযোগ্য । যদি এটি না হয় তবে আপনি কোনওভাবেই প্যাকেজে নির্ভরযোগ্যভাবে ব্যবহার করতে পারবেন না।
পাইথন ২.6 থেকে, প্যাকেজ-রেজোলিউশন উদ্দেশ্যে মডিউলটির "নাম" কেবল তার __name__
বৈশিষ্ট্য দ্বারা নয় বৈশিষ্ট্য দ্বারা নির্ধারিত হয় __package__
। এজন্য আমি __name__
মডিউলটির "নাম" উল্লেখ করতে সুস্পষ্ট প্রতীক ব্যবহার করা এড়াচ্ছি । যেহেতু পাইথন 2.6 একটি মডিউল এর "নাম" কার্যকরভাবে হয় __package__ + '.' + __name__
, বা শুধু __name__
যদি __package__
হয় None
।)