মডিউল __file__ বৈশিষ্ট্য কি পরম বা আপেক্ষিক?


107

আমি কষ্ট বোঝার হচ্ছে __file__। আমি যা বুঝি সেখান __file__থেকে মডিউলটি লোড করা হয়েছিল এমন পরম পথটি ফিরিয়ে দেয়।

এটি তৈরি করতে আমার সমস্যা হচ্ছে: আমার কাছে একটি abc.pyবিবৃতি রয়েছে print __file__, /d/projects/ python abc.pyআয় থেকে ফিরে abc.py/d/রিটার্ন থেকে চলমান projects/abc.py। কোন কারণেই কেন?



প্রাসঙ্গিক: stackoverflow.com/q/9271464/1959808
Ioannis Filippidis

উত্তর:


98

ডকুমেন্টেশন থেকে :

__file__মডিউলটি যে ফাইল থেকে লোড করা হয়েছিল সেখান থেকে ফাইলটির পথের নাম name __file__অ্যাট্রিবিউট সি মডিউল যা স্ট্যাটিক্যালি ব্যাখ্যাকারী মধ্যে সংযুক্ত থাকে উপস্থিত নয়; একটি ভাগ করা লাইব্রেরি থেকে গতিশীল লোড এক্সটেনশন মডিউলগুলির জন্য, এটি ভাগ করা লাইব্রেরি ফাইলের পথের নাম।

প্রশ্নের জবাবে @ জ্যুইডল লিঙ্কযুক্ত মেলিং তালিকা থ্রেড থেকে :

আমি এই বিশেষ উদাহরণটিকে তিরস্কার করার চেষ্টা করি নি, তবে কারণটি হ'ল আমরা প্রতিটি আমদানিতে getpwd () কল করতে চাই না বা বর্তমান ডিরেক্টরিটি ক্যাশে করার জন্য আমরা কিছু প্রকারের প্রসেস ভেরিয়েবল রাখতে চাই না। (getpwd () তুলনামূলকভাবে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ব্যর্থ হতে পারে এবং ক্যাশে দেওয়ার চেষ্টা করলে এটি ভুল হওয়ার একটি নির্দিষ্ট ঝুঁকি থাকে))

পরিবর্তে আমরা যা করি তা হ'ল সাইট.পাইয়ের কোড যা সিএস.পথের উপাদানগুলির উপরে চলে এবং সেগুলি পরম পথে পরিণত করে। তবে এই কোডটি '' sys.path এর সামনের দিকে .োকানোর আগে চলে, যাতে sys.path এর প্রাথমিক মান হয় ''।

এটির বাকিগুলির জন্য, sys.pathঅন্তর্ভুক্ত না করার বিষয়টি বিবেচনা করুন ''

সুতরাং, আপনি যদি sys.pathমডিউলটির অংশের বাইরে থাকেন তবে আপনি একটি পরম পথ পাবেন । আপনি যদি sys.pathমডিউলটির অংশটির ভিতরে থাকেন তবে আপনি একটি আপেক্ষিক পথ পাবেন

আপনি বর্তমান ডিরেক্টরির মধ্যে একটি মডিউল লোড এবং বর্তমান ডিরেক্টরির তাহলে নয় মধ্যে sys.path, আপনি একটি সুনির্দিষ্ট পাথ পাবেন।

আপনি যদি বর্তমান ডিরেক্টরিতে কোনও মডিউল লোড করেন এবং বর্তমান ডিরেক্টরিটি থাকে তবে আপনি sys.pathএকটি আপেক্ষিক পথ পাবেন।


এর অর্থ কি এই যে এর অর্থ যদি '' থেকে মডিউলটির দিকে থাকে তবে একটি আপেক্ষিক পথ ব্যবহার করা হত, যদি না পরম পথ ব্যবহার করা হত যেহেতু sys.path এর অবশিষ্ট অংশগুলি পরম ..
goh

4
আপনি বর্তমান ডিরেক্টরির মধ্যে একটি মডিউল লোড এবং বর্তমান ডিরেক্টরির তাহলে নয় মধ্যে sys.path, আপনি একটি সুনির্দিষ্ট পাথ পাবেন। আপনি যদি বর্তমান ডিরেক্টরিতে কোনও মডিউল লোড করেন এবং বর্তমান ডিরেক্টরিটি থাকে তবে আপনি sys.pathএকটি আপেক্ষিক পথ পাবেন।
agf

মনে রাখবেন, এই উদ্দেশ্যে, sys.pathঅন্তর্ভুক্ত নয় ''
agf

এটি পেয়েছে তবে @agf, যদি আমি / হোম থেকে পাইথন /foo/abc.py ব্যবহার করি তবে আমি মনে করি যে সাইজ.পথের অংশটি মডিউলটি / হোম / ফু এবং আমার বর্তমান ডিরেক্টরিটি / হোম / রয়েছে কেন, মুদ্রণ করে না ফাইল আমাকে একটি আপেক্ষিক পথ দেয়?
goh

55

__file__পাইথন ৩.৪-এর পর পর নিখুঁত , সরাসরি কোনও আপেক্ষিক পাথ ব্যবহার করে স্ক্রিপ্ট চালানো ছাড়া:

মডিউল __file__বৈশিষ্ট্য (এবং সম্পর্কিত মানগুলি) এখন সর্বদা পূর্বনির্ধারিতভাবে পরম পাথগুলি থাকা উচিত, __main__.__file__যখন কোনও স্ক্রিপ্ট সরাসরি আপেক্ষিক পাথ ব্যবহার করে কার্যকর করা হয় তার একমাত্র ব্যতিক্রম । ( বিপিও -18416 এ ব্রেট ক্যানন দ্বারা অবদান ))

যদিও এটি প্রতীকগুলি সমাধান করে কিনা তা নিশ্চিত নয়।

আপেক্ষিক পথ পাড়ি দেওয়ার উদাহরণ:

$ python script.py

1
ধন্যবাদ। এটি অনুসরণ করা একটি কঠিন সত্য!
meawoppl

4
পাইথন ৩.৪.০ ( Python 3.4.0 (default, Apr 11 2014, 13:05:11) [GCC 4.8.2] on linux) এর ক্ষেত্রে এটি সত্য নয় । এবং সিমলিঙ্কগুলি আমার পরীক্ষাগুলিতে সমাধান করা হয় না।
হিমায়িত শিখা


2
os.path.realpath(__file__)প্রতীকী লিঙ্কগুলি সমাধান করার সঠিক উপায় কি ?
কেভিনার্পে


16

দেরীতে সহজ উদাহরণ:

from os import path, getcwd, chdir

def print_my_path():
    print('cwd:     {}'.format(getcwd()))
    print('__file__:{}'.format(__file__))
    print('abspath: {}'.format(path.abspath(__file__)))

print_my_path()

chdir('..')

print_my_path()

পাইথন -২। * এর অধীনে, দ্বিতীয় কলটি সঠিকভাবে path.abspath(__file__)বর্তমান ডিরেক্টরিটির ভিত্তিতে নির্ধারণ করে :

cwd:     C:\codes\py
__file__:cwd_mayhem.py
abspath: C:\codes\py\cwd_mayhem.py
cwd:     C:\codes
__file__:cwd_mayhem.py
abspath: C:\codes\cwd_mayhem.py

@ টেকটোনিক দ্বারা উল্লিখিত হিসাবে, পাইথন ৩.৪++ এ, এটি যথাযথভাবে কাজ করবে যেহেতু __file__পরম পথে ফিরে আসে।


... __main__মডিউল ব্যতীত , যেখানে কোনও আপেক্ষিক পথ __file__ হতে পারে।
0xC0000022L

5

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

এখন site.pyপ্রারম্ভিক ফাইলটি sys.pathপ্রাথমিক ব্যতীত কেবলমাত্র নিখুঁত পাথ সরবরাহ করার যত্ন নেয় '', সুতরাং আপনি যদি পাইথোনপথ (যার পথটিও পূর্বনির্ধারণের পূর্বে নিখুঁতভাবে তৈরি করা হয় sys.path) সেট করা ব্যতীত অন্য কোনও উপায়ে এটি পরিবর্তন না করেন তবে আপনি সর্বদা একটি পরম পাবেন পাথ, কিন্তু যখন মডিউলটি বর্তমান ডিরেক্টরি মাধ্যমে অ্যাক্সেস করা হয়।

এখন আপনি যদি মজার উপায়ে sys.path চালিত হন তবে আপনি কিছু পেতে পারেন।

উদাহরণ হিসাবে আপনি একটি নমুনা মডিউল আছে যদি foo.py/tmp/কোড দিয়ে:

import sys
print(sys.path)
print (__file__)

আপনি যদি / টেম্পে যান তবে আপনি পাবেন:

>>> import foo
['', '/tmp', '/usr/lib/python3.3', ...]
./foo.py

যখন মধ্যে /home/userআপনার যোগ করা যদি /tmpআপনার PYTHONPATHআপনি পান:

>>> import foo
['', '/tmp', '/usr/lib/python3.3', ...]
/tmp/foo.py

এমনকি আপনি যুক্ত করলেও ../../tmpএটি স্বাভাবিক হবে এবং ফলাফলটি একই।

তবে যদি PYTHONPATHআপনি সরাসরি কিছু মজাদার পথ ব্যবহার না করেন তবে কারণ হিসাবে মজার হিসাবে ফল পাবেন।

>>> import sys
>>> sys.path.append('../../tmp')
>>> import foo
['', '/usr/lib/python3.3', .... , '../../tmp']
../../tmp/foo.py

গুইডো উপরোক্ত উদ্ধৃত থ্রেডে ব্যাখ্যা করেছেন, পাইথন কেন সমস্ত প্রবেশকে পরম পথে রূপান্তরের চেষ্টা করে না:

আমরা প্রতিটি আমদানিতে getpwd () কল করতে চাই না .... getpwd () তুলনামূলকভাবে ধীর এবং কখনও কখনও পুরোপুরি ব্যর্থ হতে পারে,

আপনার পথটি যেমন হয় তেমন ব্যবহার করা হয়

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