पाइथन स्क्रिप्ट के समान निर्देशिका में किसी फ़ाइल को मज़बूती से खोलने के लिए कैसे करें


157

मैं उन फाइलों को खोलता था जो वर्तमान में चल रही पायथन लिपि के समान निर्देशिका में थीं जैसे केवल एक कमांड का उपयोग करके

open("Some file.txt", "r")

हालांकि, मुझे पता चला कि जब स्क्रिप्ट को डबल-क्लिक करके विंडोज में चलाया गया था, तो यह फ़ाइल को गलत निर्देशिका से खोलने का प्रयास करेगा।

तब से मैंने फॉर्म की एक कमांड का उपयोग किया है

open(os.path.join(sys.path[0], "Some file.txt"), "r")

जब भी मैं कोई फाइल खोलना चाहता था। यह मेरे विशेष उपयोग के लिए काम करता है, लेकिन मुझे यकीन नहीं है कि sys.path[0]कुछ अन्य उपयोग के मामले में विफल हो सकता है।

तो मेरा सवाल यह है कि एक फ़ाइल को खोलने का सबसे अच्छा और सबसे विश्वसनीय तरीका क्या है जो वर्तमान में चल रहे पायथन स्क्रिप्ट के समान है?

यहाँ मैं क्या पता लगाने में सक्षम है:

  • os.getcwd()और os.path.abspath('')"वर्तमान कार्यशील निर्देशिका" लौटें, स्क्रिप्ट निर्देशिका नहीं।

  • os.path.dirname(sys.argv[0])और os.path.dirname(__file__)स्क्रिप्ट को कॉल करने के लिए उपयोग किए गए पथ पर वापस लौटें, जो सापेक्ष हो सकता है या यहां तक ​​कि रिक्त हो सकता है (यदि स्क्रिप्ट सीडब्ल्यूडी में है)। इसके अलावा, __file__मौजूद नहीं है जब स्क्रिप्ट निष्क्रिय या PythonWin में चलाया जाता है।

  • sys.path[0]और os.path.abspath(os.path.dirname(sys.argv[0]))स्क्रिप्ट निर्देशिका को वापस करने लगते हैं। मुझे यकीन नहीं है कि इन दोनों के बीच कोई अंतर है।

संपादित करें:

मुझे बस एहसास हुआ कि मैं जो करना चाहता हूं, उसे बेहतर वर्णन किया जाएगा "जिसमें एक फ़ाइल को उसी निर्देशिका में खोलें जिसमें युक्त मॉड्यूल है"। दूसरे शब्दों में, यदि मैं एक मॉड्यूल आयात करता हूं जो मैंने लिखा है कि दूसरी निर्देशिका में है, और वह मॉड्यूल एक फ़ाइल खोलता है, मैं चाहता हूं कि यह मॉड्यूल की निर्देशिका में फ़ाइल की तलाश करे। मुझे नहीं लगता कि मैंने जो कुछ भी पाया है वह ऐसा करने में सक्षम है ...

जवाबों:


199

मैं हमेशा उपयोग करता हूं:

__location__ = os.path.realpath(
    os.path.join(os.getcwd(), os.path.dirname(__file__)))

join()कॉल वर्तमान कार्यशील निर्देशिका पहले जोड़ता है, लेकिन प्रलेखन का कहना है कि अगर कुछ पथ निरपेक्ष है, अन्य सभी रास्तों इसके बारे में छोड़ दिया गिरा दिया जाता है। इसलिए, getcwd()जब dirname(__file__)एक निरपेक्ष मार्ग लौटाया जाता है।

इसके अलावा, realpathकॉल प्रतीकात्मक लिंक को हल करता है यदि कोई पाया जाता है। लिनक्स सिस्टम पर सेटप्टूल के साथ तैनाती के दौरान होने वाली परेशानियों से बचा जाता है (लिपियों को /usr/bin/कम से कम - डेबियन पर)।

आप एक ही फ़ोल्डर में फ़ाइलों को खोलने के लिए निम्नलिखित का उपयोग कर सकते हैं:

f = open(os.path.join(__location__, 'bundled-resource.jpg'));
# ...

मैं विंडोज और लिनक्स दोनों पर कई Django एप्लिकेशन के साथ संसाधनों को बंडल करने के लिए इसका उपयोग करता हूं और यह एक आकर्षण की तरह काम करता है!


4
यदि __file__उपयोग नहीं किया जा सकता है, तो sys.argv[0]इसके बजाय का उपयोग करें dirname(__file__)। बाकी लोगों को उम्मीद के मुताबिक काम करना चाहिए। मुझे __file__लाइब्रेरी कोड का उपयोग करना पसंद है , sys.argv[0]हो सकता है कि आपके कोड को बिल्कुल भी इंगित न किया जाए, यदि किसी तीसरे पक्ष की स्क्रिप्ट के माध्यम से आयात किया जाता है।
एंड्रे कारन

1
इसके साथ समस्या यह है कि अगर फ़ाइल को चलाया जा रहा है तो यह सीधे तौर पर अलग होगा या यदि यह आयात किया गया है। फ़ाइल और
sys.argv के

तो क्या यह कहना सही है कि Zimm3r के उत्तर में वर्णित भिन्नता realpath( join( getcwd(), dirname(__file__) ))यहाँ वर्णित के रूप में उपयोग करके संबोधित की गई है?
पियानोजैम

44

पायथन प्रलेखन से उद्धृत करने के लिए:

जैसा कि प्रोग्राम स्टार्टअप पर शुरू किया गया था, इस सूची का पहला आइटम, पथ [0], वह निर्देशिका है जिसमें स्क्रिप्ट शामिल है जिसका उपयोग पायथन इंटरप्रेटर को लागू करने के लिए किया गया था। यदि स्क्रिप्ट निर्देशिका उपलब्ध नहीं है (उदाहरण के लिए यदि इंटरप्रेन्योर अंतःक्रियात्मक रूप से लागू किया जाता है या यदि स्क्रिप्ट को मानक इनपुट से पढ़ा जाता है), तो पथ [0] खाली स्ट्रिंग है, जो पहले पायथन को वर्तमान निर्देशिका में खोज मॉड्यूल को निर्देशित करता है। ध्यान दें कि स्क्रिप्ट निर्देशिका PYTHONPATH के परिणामस्वरूप सम्मिलित प्रविष्टियों से पहले डाली जाती है।

sys.path [0] वही है जो आप ढूंढ रहे हैं।


10
और फ़ाइल के पूर्ण पथ के लिए os.path.join(sys.path[0], 'some file.txt'):। यह सभी प्रणालियों पर सही ढंग से रिक्त स्थान और स्लैश को संभालना चाहिए।
4

यह पहले प्रश्न का उत्तर है, EDIT के बाद का नहीं।
mcoolive

22

ठीक है यहाँ मैं क्या कर रहा हूँ

sys.argv हमेशा वह होता है जो आप टर्मिनल में टाइप करते हैं या फ़ाइल पथ के रूप में उपयोग करते हैं जब इसे python.exe या pythonw.exe के साथ निष्पादित करते हैं

उदाहरण के लिए, आप फ़ाइल टेक्स्ट को कई तरीकों से चला सकते हैं, वे प्रत्येक आपको एक अलग उत्तर देते हैं जो आपको हमेशा उस पथ को देते हैं जो अजगर टाइप किया गया था।

    C:\Documents and Settings\Admin>python test.py
    sys.argv[0]: test.py
    C:\Documents and Settings\Admin>python "C:\Documents and Settings\Admin\test.py"
    sys.argv[0]: C:\Documents and Settings\Admin\test.py

ठीक है तो पता है कि आप फ़ाइल का नाम, बहुत बड़ी बात प्राप्त कर सकते हैं, अब आवेदन निर्देशिका प्राप्त करने के लिए आप पता कर सकते हैं कि os.path, विशेष रूप से abspath और dirname का उपयोग करें

    import sys, os
    print os.path.dirname(os.path.abspath(sys.argv[0]))

कि यह उत्पादन होगा:

   C:\Documents and Settings\Admin\

यदि आप python test.py या python "C: \ Documents and Settings \ Admin \ test.py" टाइप करते हैं, तो यह हमेशा कोई फर्क नहीं पड़ेगा

__File__ के उपयोग की समस्या इन दो फाइलों पर गौर करें

import sys
import os

def paths():
        print "__file__: %s" % __file__
        print "sys.argv: %s" % sys.argv[0]

        a_f = os.path.abspath(__file__)
        a_s = os.path.abspath(sys.argv[0])

        print "abs __file__: %s" % a_f
        print "abs sys.argv: %s" % a_s

if __name__ == "__main__":
    paths()

import_test.py

import test
import sys

test.paths()

print "--------"
print __file__
print sys.argv[0]

"अजगर टेस्टोस्टेरोन" का आउटपुट

C:\Documents and Settings\Admin>python test.py
__file__: test.py
sys.argv: test.py
abs __file__: C:\Documents and Settings\Admin\test.py
abs sys.argv: C:\Documents and Settings\Admin\test.py

"अजगर test_import.py" का आउटपुट

C:\Documents and Settings\Admin>python test_import.py
__file__: C:\Documents and Settings\Admin\test.pyc
sys.argv: test_import.py
abs __file__: C:\Documents and Settings\Admin\test.pyc
abs sys.argv: C:\Documents and Settings\Admin\test_import.py
--------
test_import.py
test_import.py

जैसा कि आप देख सकते हैं कि फ़ाइल आपको हमेशा उस अजगर फ़ाइल को देती है जिसे वह चला रहा है, जहाँ से sys.argv [0] आपको वह फ़ाइल देता है जिसे आप दुभाषिया से हमेशा चलाते थे। अपनी आवश्यकताओं के आधार पर आपको यह चुनने की आवश्यकता होगी कि आपकी आवश्यकताओं में से कौन सा सबसे उपयुक्त है।


3
यह एक विस्तृत प्रमाण है कि कार्यान्वयन प्रलेखन को दर्शाता है। माना जाता__file__ है कि "हमेशा आपको वर्तमान फ़ाइल का पथ दिया जाताsys.argv[0] है ", और "हमेशा उस स्क्रिप्ट का पथ देना चाहिए जो प्रक्रिया शुरू की है"। किसी भी स्थिति __file__में, स्क्रिप्ट में उपयोग किया जाता है जो आपको हमेशा मिलता है और आपको सटीक परिणाम देता है।
एंड्रे कारोन

यदि आपके पास __file__स्क्रिप्ट के शीर्ष स्तर पर संदर्भ है , तो यह अपेक्षित रूप से काम करेगा।
मैथ्यू Schinckel

-1

मैं सफलतापूर्वक एक विशिष्ट पाठ फ़ाइल पढ़ने के साथ एक समान समस्या हो रही थी, क्योंकि मैं सफलतापूर्वक dcolish द्वारा प्रदान कोड का उपयोग करने में सक्षम था। फ़ाइल Pywon फ़ाइल की तरह cwd में नहीं है।


1
कृपया उत्तर के रूप में "धन्यवाद" न जोड़ें। एक बार जब आपके पास पर्याप्त प्रतिष्ठा होगी, तो आप उन प्रश्नों और उत्तरों को वोट करने में सक्षम होंगे जो आपको मददगार लगे। - समीक्षा से
रॉबर्टो कैबोनी

-3

मैं इसे इस तरह से करूँगा:

from os.path import abspath, exists

f_path = abspath("fooabar.txt")

if exists(f_path):
    with open(f_path) as f:
        print f.read()

उपरोक्त कोड अबस्पाट का उपयोग करके फ़ाइल के लिए एक निरपेक्ष पथ बनाता है और यह normpath(join(os.getcwd(), path))[कि pydocs से] का उपयोग करने के बराबर है । यह तब जांचता है कि क्या वह फ़ाइल वास्तव में मौजूद है और फिर इसे खोलने के लिए एक संदर्भ प्रबंधक का उपयोग करता है ताकि आपको फ़ाइल हैंडल पर कॉल बंद करने की याद न हो। IMHO, इस तरह से करने से आपको लंबे समय में बहुत दर्द से बचा जा सकेगा।


इससे पोस्टर के सवाल का जवाब नहीं मिलता है। dln385 ने विशेष रूप से कहा कि os.path.abspathस्क्रिप्ट के समान फ़ोल्डर में फ़ाइलों का पथ हल नहीं करता है यदि स्क्रिप्ट वर्तमान निर्देशिका में नहीं है।
एंड्रे कैरन

आह! मैंने मान लिया कि उपयोगकर्ता इस स्क्रिप्ट को उसी dir में चला रहा था जिस फ़ाइल को वे पढ़ना चाहते थे, कि अपने PYTHONPATH में किसी चीज़ के मॉड्यूल dir में। यही मुझे धारणाएँ बनाना सिखाएगा ...
dcolish

एब्सपैथ काम नहीं करेगा क्योंकि इस तरह के फ़ंक्शन का उपयोग करके ओएस फ़ाइल सिस्टम पर खोज करने के लिए अजगर रनटाइम के लिए असंभव है।
अक्षत ठाकर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.