पायथन में वर्तमान निष्पादित फ़ाइल का पथ मुझे कैसे मिलेगा?


193

यह एक नौसिखिया प्रश्न की तरह लग सकता है, लेकिन ऐसा नहीं है। कुछ सामान्य दृष्टिकोण सभी मामलों में काम नहीं करते हैं:

sys.argv [0]

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

__FILE__

इसका उपयोग करने का अर्थ है path = os.path.abspath(os.path.dirname(__file__)), लेकिन मैंने पाया कि यह काम नहीं करता है:

  • py2exeएक __file__विशेषता नहीं है , लेकिन एक समाधान है
  • जब आप IDLE से चलते हैं तो execute()कोई __file__विशेषता नहीं होती है
  • ओएस एक्स 10.6 जहां मुझे मिलता है NameError: global name '__file__' is not defined

अधूरे जवाब के साथ संबंधित प्रश्न:

मैं एक सामान्य समाधान ढूंढ रहा हूं , एक जो उपरोक्त सभी उपयोग के मामलों में काम करेगा।

अपडेट करें

यहाँ एक टेस्टकेस का परिणाम है:

अजगर के ओरेकल का उत्पादन (विंडोज पर)

a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz

b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz

a.py

#! /usr/bin/env python
import os, sys

print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print

execfile("subdir/b.py")

subdir / b.py

#! /usr/bin/env python
import os, sys

print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print

पेड़

C:.
|   a.py
\---subdir
        b.py

जवाबों:


80

आप सीधे निष्पादित की जा रही मुख्य स्क्रिप्ट का स्थान निर्धारित नहीं कर सकते। सब के बाद, कभी-कभी स्क्रिप्ट एक फ़ाइल से बिल्कुल नहीं आती थी। उदाहरण के लिए, यह इंटरएक्टिव इंटरप्रेटर या डायनामिकली जेनरेट किए गए कोड से ही मेमोरी में स्टोर हो सकता है।

हालाँकि, आप मज़बूती से किसी मॉड्यूल का स्थान निर्धारित कर सकते हैं, क्योंकि मॉड्यूल हमेशा फ़ाइल से लोड होते हैं। यदि आप निम्नलिखित कोड के साथ एक मॉड्यूल बनाते हैं और इसे अपनी मुख्य स्क्रिप्ट के समान निर्देशिका में डालते हैं, तो मुख्य स्क्रिप्ट मॉड्यूल को आयात कर सकती है और खुद का पता लगाने के लिए उपयोग कर सकती है।

some_path / module_locator.py:

def we_are_frozen():
    # All of the modules are built-in to the interpreter, e.g., by py2exe
    return hasattr(sys, "frozen")

def module_path():
    encoding = sys.getfilesystemencoding()
    if we_are_frozen():
        return os.path.dirname(unicode(sys.executable, encoding))
    return os.path.dirname(unicode(__file__, encoding))

some_path / main.py:

import module_locator
my_path = module_locator.module_path()

यदि आपके पास अलग-अलग निर्देशिकाओं में कई मुख्य स्क्रिप्ट हैं, तो आपको मॉड्यूल_लोकेटर की एक से अधिक प्रतिलिपि की आवश्यकता हो सकती है।

बेशक, यदि आपकी मुख्य स्क्रिप्ट किसी अन्य उपकरण से भरी हुई है जो आपको मॉड्यूल को आयात करने की अनुमति नहीं देती है जो आपकी स्क्रिप्ट के साथ सह-स्थित हैं, तो आप भाग्य से बाहर हैं। इस तरह के मामलों में, आपके द्वारा की जाने वाली जानकारी आपके कार्यक्रम में कहीं भी मौजूद नहीं होती है। आपका सबसे अच्छा शर्त टूल के लेखकों के साथ बग दर्ज करना होगा।


2
मैं उल्लेख करता हूं कि ओएस 10.6 पर मुझे फ़ाइलNameError: global name '__file__' is not defined का उपयोग करना है और यह आईडीएलई के अंदर नहीं है। सोचें कि __file__केवल मॉड्यूल के अंदर परिभाषित किया गया है।
सोरिन

1
@ सोरिन सर्बनेया: मैंने अपने उत्तर को इस बात से अपडेट किया कि मैं उसके आसपास कैसे पहुँचता हूँ।
डैनियल स्टुट्ज़बाक

2
धन्यवाद, लेकिन वास्तव में गायब होने की समस्या का __file__यूनिकोड से कोई लेना-देना नहीं था। मुझे नहीं पता कि क्यों __file__परिभाषित नहीं किया गया है, लेकिन मैं एक सामान्य समाधान ढूंढ रहा हूं, यह सभी मामलों में काम करेगा।
सोरिन

1
क्षमा करें, यह सभी मामलों में संभव नहीं है। उदाहरण के लिए, मैं एक wscript फ़ाइल (अजगर) के अंदर से waf.googlecode.com में ऐसा करने की कोशिश करता हूं। इन फ़ाइलों को निष्पादित किया जाता है, लेकिन वे मॉड्यूल नहीं हैं और आप उन्हें मॉड्यूल नहीं बना सकते हैं (वे स्रोत पेड़ से किसी भी उपनिर्देशिका हो सकते हैं)।
सोरिन

1
क्या some_path/module_locator.pyइसके बदले आपको स्थान नहीं दिया जाएगा ?
केसबश

68

सबसे पहले, आपको inspectऔर से आयात करने की आवश्यकता हैos

from inspect import getsourcefile
from os.path import abspath

अगला, जहाँ भी आप स्रोत फ़ाइल को आप से ढूंढना चाहते हैं, बस उपयोग करें

abspath(getsourcefile(lambda:0))

सबसे बढ़िया उत्तर। धन्यवाद।
देवन विलियम्स

4
बहुत बढ़िया जवाब। धन्यवाद। यह भी सबसे कम और सबसे पोर्टेबल (विभिन्न ओएस-एस पर चल रहा है) उत्तर लगता है और इस तरह की समस्याओं का सामना नहीं करता है NameError: global name '__file__' is not defined(एक और समाधान जिसके कारण)।
एडवर्ड

एक और संभावना जो समान रूप से कम है lambda:_:। यह मेरे लिए काम करता है - यकीन नहीं है कि यह हमेशा काम करेगा। lambda:0शायद कुछ अथाह छोटी राशि (या शायद इतनी छोटी नहीं ... या 0लोड ग्लोबल के लिए एक लोड भी तेजी से हो सकता है _) के माध्यम से तेजी से चलाता है। क्या यह क्लीनर या पढ़ने में आसान है या अधिक चतुर / अस्पष्ट है।
आर्टऑफवर्फ

जैसा कि मैंने लगभग हर प्रस्ताव के साथ किया है, यह सिर्फ मेरे लिए cwd देता है, न कि निर्देशिका फ़ाइल जो मैं चला रहा हूं (डिबगिंग)।
जेम्स

1
@ नाम - यह कोड आपके द्वारा चलाए जा रहे फ़ाइल में जाता है ... चलाना getsourcefile(lambda:0)व्यर्थ हो जाएगा और Noneयदि आप इसे इंटरेक्टिव प्रॉम्प्ट पर चलाने का प्रयास करते हैं तो वापस आ lambdaजाएंगे (क्योंकि यह किसी भी स्रोत फ़ाइल में नहीं होगा।) यदि आप जानना चाहते हैं। जहां एक अन्य कार्य या वस्तु एक संवादात्मक वातावरण से आ रही है, शायद abspath(getsourcefile(thatFunctionOrObject))आपके लिए अधिक उपयोगी होगी?
आर्टऑफवर्फ सेप

16

यह समाधान निष्पादनों में भी मजबूत है

import inspect, os.path

filename = inspect.getframeinfo(inspect.currentframe()).filename
path     = os.path.dirname(os.path.abspath(filename))

2
यह सही उत्तर होना चाहिए। यह भी काम करता है entry_point: console_script, लेकिन अन्य उत्तरों में से कोई भी नहीं।
पोलव

15

मैं एक समान समस्या में चल रहा था, और मुझे लगता है कि इससे समस्या हल हो सकती है:

def module_path(local_function):
   ''' returns the module path without the use of __file__.  Requires a function defined
   locally in the module.
   from http://stackoverflow.com/questions/729583/getting-file-path-of-imported-module'''
   return os.path.abspath(inspect.getsourcefile(local_function))

यह नियमित स्क्रिप्ट और बेकार में काम करता है। मैं बस इतना ही कह सकता हूं कि इसे दूसरों के लिए आजमाया जाए!

मेरा सामान्य उपयोग:

from toolbox import module_path
def main():
   pass # Do stuff

global __modpath__
__modpath__ = module_path(main)

अब मैं __file__ के बजाय __modpath__ का उपयोग करता हूं।


2
PEP8 कोडिंग स्टाइल गाइड के अनुसार , किसी को डबल अग्रणी और अनुगामी अंडरस्कोर वाले नाम नहीं बनाने __modpath__चाहिए - इसलिए इसका नाम बदला जाना चाहिए। आप भी शायद globalबयान की जरूरत नहीं है । नहीं तो +1!
मार्टीन्यू

4
वास्तव में आप कॉल करने के लिए स्थानीय फ़ंक्शन को सही में परिभाषित कर सकते हैं module_path()। यानी module_path(lambda _: None)जो स्क्रिप्ट की अन्य सामग्री पर निर्भर नहीं करता है, वह है
मार्टीन्यू

@martineau: मैंने आपका सुझाव लिया lambda _: Noneऔर पिछले लगभग दो वर्षों से इसका उपयोग किया है, लेकिन अभी-अभी मुझे पता चला है कि मैं इसे संक्षेप में बता सकता हूं lambda:0। क्या कोई विशेष कारण है जो आपने सुझाया है कि आपने जिस तर्क की अनदेखी की है _, उसके बदले में कोई तर्क नहीं दिया है? क्या Noneकिसी स्थान के साथ उपसर्ग करने के बजाय कुछ श्रेष्ठ है 0? वे दोनों समान रूप से गूढ़ हैं, मुझे लगता है, सिर्फ एक 8 वर्णों का लंबा है, जबकि दूसरा 14 वर्णों का लंबा है।
ArtOfWarfare

@ArtOfWarfare: दोनों के बीच का अंतर यह है कि lambda _:एक ऐसा फंक्शन है जो एक तर्क लेता है और lambda:एक है जो किसी को नहीं लेता है। इससे कोई फर्क नहीं पड़ता क्योंकि फ़ंक्शन को कभी नहीं कहा जाता है। इसी तरह यह मायने नहीं रखता कि रिटर्न वैल्यू का क्या उपयोग किया जाता है। मुझे लगता है कि मैंने चुना Noneक्योंकि उस समय ऐसा लगता था कि यह कुछ भी नहीं है, कभी-कभी-कभी-कभी बेहतर कार्य करता है। इसके सामने का स्थान वैकल्पिक है और फिर से केवल बेहतर पठनीयता के लिए (हमेशा PEP8 का पालन करने की कोशिश करना आदत है)।
मार्टिन्यू

@ स्मार्टिन्यू: यह स्पष्ट रूप से एक दुरुपयोग है, lambdaहालांकि इसका उपयोग किसी ऐसी चीज के लिए किया जाता है जो कभी करने के लिए नहीं थी। यदि आप PEP8 का अनुसरण करते हैं, तो मुझे लगता है कि इसके लिए सही सामग्री होगी pass, नहीं None, लेकिन यह एक बयान में मान्य नहीं है lambda, इसलिए आपको मूल्य के साथ कुछ करना होगा। कुछ मान्य 2 वर्ण चीजें हैं, जिन्हें आप रख सकते हैं, लेकिन मुझे लगता है कि केवल वही मान्य एकल वर्ण चीजें हैं जिन्हें आप 0-9 में डाल सकते हैं (या किसी एकल वर्ण चर नाम के बाहर असाइन किया गया है lambda)। मुझे 0सबसे अच्छा चित्र 0- की शून्यता का संकेत देता है। 9।
आर्टऑफवर्फ

6

संक्षिप्त उत्तर यह है कि आपके द्वारा वांछित जानकारी प्राप्त करने का कोई गारंटीकृत तरीका नहीं है , हालांकि ऐसी विधियां हैं जो लगभग हमेशा व्यवहार में काम करती हैं। आप देख सकते हैं कि मुझे C में निष्पादन योग्य का स्थान कैसे मिल सकता है? । यह सी बिंदु से समस्या पर चर्चा करता है, लेकिन प्रस्तावित समाधान आसानी से पायथन में स्थानांतरित हो जाते हैं।


नमस्कार, मेरा ध्वज अस्वीकृत कर दिया गया था इसलिए मैंने अब मेटा पर एक चर्चा शुरू की है: meta.stackoverflow.com/questions/277272/…
ArtOfWarfare

हालाँकि इस पृष्ठ पर पहले से ही सरल कार्य कर रहे हैं। मेरे समाधान अच्छी तरह से काम करता है: stackoverflow.com/a/33531619/3787376
एडवर्ड

5

प्रश्न के लिए मेरा उत्तर देखें संबंधित जानकारी के लिए मूल फ़ोल्डर से मॉड्यूल आयात करना , इसमें यह भी शामिल है कि मेरा उत्तर अविश्वसनीय __file__चर का उपयोग क्यों नहीं करता है । यह सरल समाधान मॉड्यूल के रूप में विभिन्न ऑपरेटिंग सिस्टम के साथ क्रॉस-संगत होना चाहिए osऔर inspectपायथन के हिस्से के रूप में आना चाहिए।

सबसे पहले, आपको निरीक्षण और ओएस मॉड्यूल के कुछ हिस्सों को आयात करने की आवश्यकता है ।

from inspect import getsourcefile
from os.path import abspath

इसके बाद, अपने पायथन कोड में कहीं और निम्न पंक्ति का उपयोग करें:

abspath(getsourcefile(lambda:0))

यह काम किस प्रकार करता है:

अंतर्निहित मॉड्यूल os(नीचे विवरण) से, abspathउपकरण आयात किया जाता है।

Mac, NT या Posix के लिए OS रूट किस सिस्टम पर निर्भर करता है।

तब getsourcefile(नीचे विवरण) अंतर्निहित मॉड्यूल से आयात किया जाता है inspect

लाइव पायथन वस्तुओं से उपयोगी जानकारी प्राप्त करें।

  • abspath(path) फ़ाइल पथ का पूर्ण / पूर्ण संस्करण लौटाता है
  • getsourcefile(lambda:0)किसी तरह लैम्ब्डा फ़ंक्शन ऑब्जेक्ट की आंतरिक स्रोत फ़ाइल मिलती है, इसलिए '<pyshell#nn>'पायथन शेल में वापस आती है या वर्तमान में निष्पादित किए जा रहे पायथन कोड का फ़ाइल पथ देता है।

का प्रयोग abspathके परिणाम पर getsourcefile(lambda:0)लगता है कि उत्पन्न फ़ाइल पथ अजगर फ़ाइल का पूरा फ़ाइल पथ है बनाना चाहिए।
यह समझाया गया समाधान मूल रूप से कोड से उत्तर पर आधारित था कि मैं पायथन में वर्तमान निष्पादित फ़ाइल का पथ कैसे प्राप्त करूं?


हाँ, मैं बस एक ही समाधान के साथ आया था ... जवाबों से बेहतर है कि बस यह कहो कि यह मज़बूती से नहीं किया जा सकता है ... जब तक कि सवाल यह नहीं पूछ रहा है कि मुझे क्या लगता है ...
ग्रैडी प्लेयर

5

आपने बस फोन किया है:

path = os.path.abspath(os.path.dirname(sys.argv[0]))

के बजाय:

path = os.path.dirname(os.path.abspath(sys.argv[0]))

abspath()आपको इसका पूर्ण पथ देता है sys.argv[0](फ़ाइलनाम आपका कोड है) और dirname()फ़ाइल नाम के बिना निर्देशिका पथ देता है।


3

इसे क्रॉस-प्लेटफ़ॉर्म तरीके से करना चाहिए (जब तक आप इंटरप्रेटर या कुछ का उपयोग नहीं कर रहे हों):

import os, sys
non_symbolic=os.path.realpath(sys.argv[0])
program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))

sys.path[0]वह निर्देशिका है जो आपकी कॉलिंग स्क्रिप्ट में है (पहला स्थान यह उस स्क्रिप्ट द्वारा उपयोग किए जाने वाले मॉड्यूल के लिए दिखता है)। हम फ़ाइल का नाम खुद ही ले सकते हैं sys.argv[0](जो मैंने किया था os.path.basename)। os.path.joinबस उन्हें एक क्रॉस-प्लेटफॉर्म तरीके से एक साथ चिपका दिया। os.path.realpathबस यह सुनिश्चित करता है कि यदि हमें स्क्रिप्ट से अलग नामों के साथ कोई प्रतीकात्मक लिंक मिलता है या नहीं, तब भी हमें स्क्रिप्ट का असली नाम मिल जाता है।

मेरे पास मैक नहीं है; इसलिए, मैंने इस पर एक परीक्षण नहीं किया है। कृपया मुझे बताएं कि क्या यह काम करता है, जैसा कि ऐसा लगता है कि इसे करना चाहिए। मैंने पायथन 3.4 के साथ लिनक्स (एक्सूबंटू) में इसका परीक्षण किया। ध्यान दें कि इस समस्या के कई समाधान Mac पर काम नहीं करते हैं (क्योंकि मैंने सुना है कि __file__Mac पर मौजूद नहीं है)।

ध्यान दें कि यदि आपकी स्क्रिप्ट एक प्रतीकात्मक लिंक है, तो यह आपको उस फ़ाइल का पथ देगा जो इसे लिंक करती है (और प्रतीकात्मक लिंक का पथ नहीं)।


2

आप मॉड्यूल Pathसे उपयोग कर सकते हैं pathlib:

from pathlib import Path

# ...

Path(__file__)

आप parentपथ में आगे जाने के लिए कॉल का उपयोग कर सकते हैं :

Path(__file__).parent

यह उत्तर __file__चर का उपयोग करता है जो अविश्वसनीय हो सकता है (हमेशा पूर्ण फ़ाइल पथ नहीं है, हर ऑपरेटिंग सिस्टम आदि पर काम नहीं करता है) जैसा कि स्टैकऑवरफ्लो उपयोगकर्ताओं ने अक्सर उल्लेख किया है। इसमें शामिल नहीं होने के जवाब को बदलने से समस्याएं कम होंगी और अधिक क्रॉस-संगत होगी। अधिक जानकारी के लिए, stackoverflow.com/a/33532002/3787376 देखें ।
एडवर्ड

@ mrroot5 ठीक है, तो कृपया अपनी टिप्पणी हटा दें।
गैवरियल कोहेन

1

यदि कोड किसी फ़ाइल से आ रहा है, तो आप उसका पूरा नाम प्राप्त कर सकते हैं

sys._getframe().f_code.co_filename

आप फ़ंक्शन का नाम भी पुनः प्राप्त कर सकते हैं f_code.co_name


0

बस निम्नलिखित जोड़ें:

from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)

या:

from sys import *
print(sys.argv[0])

0

मेरा समाधान है:

import os
print(os.path.dirname(os.path.abspath(__file__)))

-1
import os
current_file_path=os.path.dirname(os.path.realpath('__file__'))

इसका कोई अर्थ नहीं है। पहले, '__file__'एक स्ट्रिंग नहीं होना चाहिए, दूसरा, यदि आपने किया है __file__, तो यह केवल उस फ़ाइल के लिए काम करेगा जो कोड की यह पंक्ति है, और निष्पादित फ़ाइल नहीं है?
एंड्रियास स्टॉरविक स्ट्रोमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.