क्या मॉड्यूल __file__ विशेषता पूर्ण या सापेक्ष है?


107

मुझे समझने में दिक्कत हो रही है __file__। जो मैं समझता हूं, __file__उस पूर्ण पथ को लौटाता है जिससे मॉड्यूल लोड किया गया था।

मुझे इसे बनाने में समस्या हो रही है: मेरे पास abc.pyएक कथन है print __file__, /d/projects/ python abc.pyरिटर्न से चल रहा है abc.py। /d/रिटर्न से चल रहा है projects/abc.py। कोई भी कारण क्यों?


10
यहाँ इस बारे में गुइडो का क्या कहना है: mail.python.org/pipermail/python-dev/2010-Febdays/097461.html
— kindall 19'11

जवाबों:


98

से प्रलेखन :

__file__उस फ़ाइल का पथनाम है जिसमें से मॉड्यूल लोड किया गया था, अगर वह फ़ाइल से लोड किया गया था। __file__विशेषता सी मॉड्यूल है कि स्थिर दुभाषिया में जुड़े हुए हैं के लिए मौजूद नहीं है; साझा पुस्तकालय से गतिशील रूप से लोड किए गए विस्तार मॉड्यूल के लिए, यह साझा लाइब्रेरी फ़ाइल का पथनाम है।

से मेलिंग सूची धागा प्रश्न के लिए एक टिप्पणी में @kindall से जुड़े हुए:

मैंने इस विशेष उदाहरण को दोहराने की कोशिश नहीं की है, लेकिन इसका कारण यह है कि हम हर आयात पर गेटपेड () को कॉल नहीं करना चाहते हैं और न ही हम वर्तमान निर्देशिका को कैश करने के लिए कुछ प्रकार की इन-प्रोसेस चर चाहते हैं। (getpwd () अपेक्षाकृत धीमा है और कभी-कभी एकमुश्त विफल हो सकता है, और इसे कैश करने की कोशिश करने से गलत होने का एक निश्चित जोखिम होता है।)

इसके बजाय हम क्या करते हैं, साइटकैम में कोड है जो sys.path के तत्वों पर चलता है और उन्हें पूर्ण पथ में बदल देता है। हालाँकि यह कोड '' sys.path के सामने डालने से पहले चलता है, ताकि sys.path का प्रारंभिक मान '' हो।

इसके बाकी हिस्सों के sys.pathलिए, शामिल न करने पर विचार करें ''।

इसलिए, यदि आप उस भाग के बाहर हैं, sys.pathजिसमें मॉड्यूल शामिल है, तो आपको एक पूर्ण मार्ग मिलेगा । यदि आप उस हिस्से के अंदर हैं, sys.pathजिसमें मॉड्यूल शामिल है, तो आपको एक सापेक्ष मार्ग मिलेगा ।

यदि आप वर्तमान निर्देशिका में एक मॉड्यूल लोड करते हैं, और वर्तमान निर्देशिका में नहीं है sys.path, तो आपको एक पूर्ण मार्ग मिलेगा।

आप वर्तमान निर्देशिका में एक मॉड्यूल लोड, और वर्तमान निर्देशिका तो है में sys.path, आप एक रिश्तेदार पथ मिलेगा।


तो क्या इसका मतलब यह है कि यदि मॉड्यूल के लिए '' से एक रास्ता है, तो एक सापेक्ष पथ का उपयोग किया जाएगा, यदि शेष रास्तों के बाद से निरपेक्ष पथ का उपयोग नहीं किया जाएगा। संपूर्ण हैं ..
— goh

4
यदि आप वर्तमान निर्देशिका में एक मॉड्यूल लोड करते हैं, और वर्तमान निर्देशिका में नहीं है sys.path, तो आपको एक पूर्ण मार्ग मिलेगा। आप वर्तमान निर्देशिका में एक मॉड्यूल लोड, और वर्तमान निर्देशिका तो है में sys.path, आप एक रिश्तेदार पथ मिलेगा।
— अगफ

इस उद्देश्य के लिए याद रखें, sys.pathइसमें शामिल नहीं है ''।
— अगफ

मिल गया, लेकिन @agf, अगर मैं / घर से python /foo/abc.py का उपयोग करता हूं, तो मुझे लगता है कि इसमें sys.path का हिस्सा है जिसमें मॉड्यूल / घर / foo है और मेरी वर्तमान निर्देशिका / घर / है, प्रिंट क्यों करता है फ़ाइल मुझे एक रिश्तेदार रास्ता देता है?
— गोह

55

__file__पायथन 3.4 के बाद से निरपेक्ष है , सिवाय एक स्क्रिप्ट को निष्पादित करते हुए सीधे एक रिश्तेदार पथ का उपयोग करते हुए:

मॉड्यूल __file__विशेषताएँ (और संबंधित मूल्य) में हमेशा डिफ़ॉल्ट रूप से पूर्ण पथ होना चाहिए, एकमात्र अपवाद के साथ __main__.__file__जब किसी स्क्रिप्ट को किसी रिश्तेदार पथ का उपयोग करके सीधे निष्पादित किया गया हो। ( बॉट -18416 में ब्रेट तोप द्वारा योगदान दिया गया ।)

यकीन नहीं होता कि यह सिमिलिंक को हल करता है।

एक रिश्तेदार मार्ग से गुजरने का उदाहरण:

$ python script.py

1
धन्यवाद। यह नीचे ट्रैक करने के लिए एक कठिन तथ्य है!
— मेवोप्लप

4
यह पायथन 3.4.0 ( Python 3.4.0 (default, Apr 11 2014, 13:05:11) [GCC 4.8.2] on linux) के लिए सही नहीं है । और मेरे परीक्षणों में सिम्बल का समाधान नहीं किया गया है।
— फ्रोजन फ्लेम

@FrozenFlame, के लिए रिपोर्ट करने के लिए स्वतंत्र महसूस bugs.python.org यदि 3.4.1 इसे ठीक नहीं है।
— अनातोली टेकटोनिक

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()

पायथन -2 *। के तहत, दूसरी कॉल गलत तरीके 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

जैसा कि @techtonik ने उल्लेख किया है, पायथन 3.4+ में, यह __file__एक निरपेक्ष पथ के बाद से ठीक काम करेगा ।


... __main__मॉड्यूल को छोड़कर , जहां एक सापेक्ष पथ __file__ हो सकता है।
— 0xC0000022L

5

@Kindall द्वारा प्रदान की गई गुइडो मेल की मदद से, हम मानक आयात प्रक्रिया को समझने की कोशिश कर सकते हैं क्योंकि प्रत्येक सदस्य में मॉड्यूल को खोजने की कोशिश की जा रही है sys.path, और इस लुकअप के परिणाम के रूप में फ़ाइल करें ( PyMOTW मॉड्यूल और आयात में अधिक विवरण ।)। इसलिए यदि मॉड्यूल sys.pathपरिणाम में एक पूर्ण पथ में स्थित है, तो निरपेक्ष है, लेकिन यदि यह sys.pathपरिणाम में एक सापेक्ष पथ में स्थित है, तो सापेक्ष है।

अब site.pyस्टार्टअप फाइल sys.pathप्रारंभिक के अलावा केवल पूर्ण पथ देने में ध्यान रखती है '', इसलिए यदि आप PYTHONPATH (जिसका पथ भी पूर्ण बनाया गया है, उपसर्ग से पहले sys.path) सेट करने के अलावा अन्य माध्यमों से इसे नहीं बदलते हैं , तो आपको हमेशा एक पूर्ण मिलेगा पथ, लेकिन जब मॉड्यूल को वर्तमान निर्देशिका के माध्यम से एक्सेस किया जाता है।

अब अगर आप अजीब तरीके से sys.path को ट्रिक करते हैं तो आपको कुछ भी मिल सकता है।

उदाहरण के लिए यदि आपके पास कोड के साथ एक नमूना मॉड्यूल foo.pyहै /tmp/:

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

यदि आप / tmp में जाते हैं:

>>> 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 () अपेक्षाकृत धीमा है और कभी-कभी एकमुश्त,

तो आपके रास्ते का उपयोग किया जाता है जैसा कि यह है ।

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