كيف يمكنني الحصول على مسار واسم الملف الذي يتم تنفيذه حاليًا؟

StackOverflow https://stackoverflow.com/questions/50499

  •  09-06-2019
  •  | 
  •  

سؤال

لدي برامج نصية تستدعي ملفات البرامج النصية الأخرى ولكنني بحاجة للحصول على مسار الملف الذي يتم تشغيله حاليًا ضمن العملية.

على سبيل المثال، لنفترض أن لدي ثلاثة ملفات.استخدام com.execfile:

  • script_1.py المكالمات script_2.py.
  • بدوره، script_2.py المكالمات script_3.py.

كيف يمكنني الحصول على اسم الملف ومساره script_3.py, من الكود داخل script_3.py, ، دون الحاجة إلى تمرير تلك المعلومات كوسائط من script_2.py?

(تنفيذ os.getcwd() إرجاع مسار ملف البرنامج النصي الأصلي وليس الملف الحالي.)

هل كانت مفيدة؟

المحلول

ص1.py:

execfile("p2.py")

ص2.py:

import inspect, os
print inspect.getfile(inspect.currentframe()) # script filename (usually with path)
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # script directory

نصائح أخرى

__file__

كما قال آخرون.قد ترغب أيضًا في الاستخدام os.path.realpath لإزالة الروابط الرمزية:

import os

os.path.realpath(__file__)

تحديث 2018-11-28:

فيما يلي ملخص للتجارب مع Python 2 و 3.مع

main.py - يعمل foo.py
foo.py - يقوم بتشغيل lib/bar.py
lib/bar.py - يطبع تعبيرات مسار الملف

| Python | Run statement       | Filepath expression                    |
|--------+---------------------+----------------------------------------|
|      2 | execfile            | os.path.abspath(inspect.stack()[0][1]) |
|      2 | from lib import bar | __file__                               |
|      3 | exec                | (wasn't able to obtain it)             |
|      3 | import lib.bar      | __file__                               |

بالنسبة إلى Python 2، قد يكون من الواضح التبديل إلى الحزم حتى يمكن استخدامها from lib import bar - فقط أضف فارغة __init__.py الملفات إلى المجلدين.

بالنسبة لبيثون 3، execfile غير موجود - البديل الأقرب هو exec(open(<filename>).read()), ، على الرغم من أن هذا يؤثر على إطارات المكدس.إنها أبسط طريقة للاستخدام فقط import foo و import lib.bar - لا __init__.py الملفات المطلوبة.

أنظر أيضا الفرق بين الاستيراد والملف التنفيذي


الجواب الأصلي:

فيما يلي تجربة تعتمد على الإجابات الموجودة في هذا الموضوع - مع Python 2.7.10 على نظام التشغيل Windows.

تلك القائمة على المكدس هي الوحيدة التي يبدو أنها تعطي نتائج موثوقة.الأخيران لهما أقصر بناء جملة, ، أي.-

print os.path.abspath(inspect.stack()[0][1])                   # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1]))  # C:\filepaths\lib

هنا يتم إضافة هذه إلى sys كوظائف!الائتمان لUsagi وpablog

بناءً على الملفات الثلاثة التالية، وتشغيل main.py من المجلد الخاص به باستخدام python main.py (جرب أيضًا ملفات execfiles ذات المسارات المطلقة والاتصال من مجلد منفصل).

C:\filepaths\main.py: execfile('foo.py')
C:\filepaths\foo.py: execfile('lib/bar.py')
C:\filepaths\lib\bar.py:

import sys
import os
import inspect

print "Python " + sys.version
print

print __file__                                        # main.py
print sys.argv[0]                                     # main.py
print inspect.stack()[0][1]                           # lib/bar.py
print sys.path[0]                                     # C:\filepaths
print

print os.path.realpath(__file__)                      # C:\filepaths\main.py
print os.path.abspath(__file__)                       # C:\filepaths\main.py
print os.path.basename(__file__)                      # main.py
print os.path.basename(os.path.realpath(sys.argv[0])) # main.py
print

print sys.path[0]                                     # C:\filepaths
print os.path.abspath(os.path.split(sys.argv[0])[0])  # C:\filepaths
print os.path.dirname(os.path.abspath(__file__))      # C:\filepaths
print os.path.dirname(os.path.realpath(sys.argv[0]))  # C:\filepaths
print os.path.dirname(__file__)                       # (empty string)
print

print inspect.getfile(inspect.currentframe())         # lib/bar.py

print os.path.abspath(inspect.getfile(inspect.currentframe())) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:\filepaths\lib
print

print os.path.abspath(inspect.stack()[0][1])          # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1]))  # C:\filepaths\lib
print

أعتقد أن هذا أنظف:

import inspect
print inspect.stack()[0][1]

ويحصل على نفس المعلومات مثل:

print inspect.getfile(inspect.currentframe())

حيث [0] هو الإطار الحالي في المكدس (أعلى المكدس) و[1] هو اسم الملف، قم بالزيادة للرجوع إلى الخلف في المكدس، أي.

print inspect.stack()[1][1]

سيكون اسم ملف البرنامج النصي الذي يسمى الإطار الحالي.كما أن استخدام [-1] سيوصلك إلى أسفل المكدس، وهو نص الاستدعاء الأصلي.

import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only

تعتبر الاقتراحات التي تم وضع علامة عليها كأفضل اقتراحات صحيحة إذا كان البرنامج النصي الخاص بك يتكون من ملف واحد فقط.

إذا كنت تريد معرفة اسم الملف القابل للتنفيذ (أي.الملف الجذر الذي تم تمريره إلى مترجم بايثون للبرنامج الحالي) من ملف يمكن استيراده كوحدة نمطية، عليك القيام بذلك (لنفترض أن هذا موجود في ملف اسمه foo.py):

import inspect

print inspect.stack()[-1][1]

لأن آخر شيء ([-1]) على المكدس هو أول ما تم إدخاله فيه (المكدسات عبارة عن هياكل بيانات LIFO/FILO).

ثم في الملف bar.py اذا أنت import foo سيتم طباعته bar.py, ، بدلا من foo.py, ، والتي ستكون قيمة كل هذه:

  • __file__
  • inspect.getfile(inspect.currentframe())
  • inspect.stack()[0][1]
import os
print os.path.basename(__file__)

هذا سيعطينا اسم الملف فقط.أي.إذا كان abspath للملف هو c:\abcd\abc.py، فسيقوم السطر الثاني بطباعة abc.py

ليس من الواضح تمامًا ما تقصده بـ "مسار الملف الذي يتم تشغيله حاليًا ضمن العملية".sys.argv[0] يحتوي عادةً على موقع البرنامج النصي الذي تم استدعاؤه بواسطة مترجم Python.افحص ال وثائق النظام لمزيد من التفاصيل.

كما أشار @Tim و@Pat Notz، توفر السمة __file__ إمكانية الوصول إليها

الملف الذي تم من خلاله تحميل الوحدة ، إذا تم تحميله من ملف

لدي برنامج نصي يجب أن يعمل تحت بيئة ويندوز.هذا الرمز الذي تم قصه هو ما انتهيت منه:

import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])

إنه قرار خرقاء تمامًا.لكنه لا يتطلب مكتبات خارجية وهذا هو الشيء الأكثر أهمية في حالتي.

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

لا حاجة للتفتيش أو أي مكتبة أخرى.

لقد نجح هذا الأمر بالنسبة لي عندما اضطررت إلى استيراد برنامج نصي (من دليل مختلف ثم البرنامج النصي الذي تم تنفيذه)، والذي يستخدم ملف تكوين موجود في نفس المجلد مثل البرنامج النصي المستورد.

ال __file__ تعمل السمة لكل من الملف الذي يحتوي على رمز التنفيذ الرئيسي وكذلك الوحدات النمطية المستوردة.

يرى https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__

import sys

print sys.path[0]

سيؤدي هذا إلى طباعة مسار البرنامج النصي الذي يتم تنفيذه حاليًا

أعتقد أنه مجرد __file__ يبدو أنك قد ترغب أيضًا في التحقق من فحص الوحدة النمطية.

يمكنك استخدام inspect.stack()

import inspect,os
inspect.stack()[0]  => (<frame object at 0x00AC2AC0>, 'g:\\Python\\Test\\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()[0]\n'], 0)
os.path.abspath (inspect.stack()[0][1]) => 'g:\\Python\\Test\\_GetCurrentProgram.py'

جرب هذا،

import os
os.path.dirname(os.path.realpath(__file__))
import sys
print sys.argv[0]

يجب أن يعمل هذا:

import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))

للحصول على دليل تنفيذ البرنامج النصي

 print os.path.dirname( inspect.getfile(inspect.currentframe()))

للحفاظ على تناسق الترحيل عبر الأنظمة الأساسية (macOS/Windows/Linux)، حاول:

path = r'%s' % os.getcwd().replace('\\','/')

print(__file__)
print(__import__("pathlib").Path(__file__).parent)

لقد استخدمت النهج مع __file__
os.path.abspath(__file__)
ولكن هناك القليل من الخدعة ، فهو يرجع ملف .py عند تشغيل الرمز في المرة الأولى ، تتم تشغيله التالي اسم ملف *.pyc
لذلك بقيت مع:
inspect.getfile(inspect.currentframe())
أو
sys._getframe().f_code.co_filename

لقد كتبت دالة تأخذ بعين الاعتبار الكسوف مصحح الأخطاء و com.unittest.يقوم بإرجاع مجلد البرنامج النصي الأول الذي تقوم بتشغيله.يمكنك اختياريًا تحديد __ملف__ var، ولكن الشيء الرئيسي هو أنه ليس عليك مشاركة هذا المتغير عبر جميع ملفاتك استدعاء التسلسل الهرمي.

ربما يمكنك التعامل مع الآخرين في حالات معينة لم أرها، لكن بالنسبة لي لا بأس.

import inspect, os
def getRootDirectory(_file_=None):
    """
    Get the directory of the root execution file
    Can help: http://stackoverflow.com/questions/50499/how-do-i-get-the-path-and-name-of-the-file-that-is-currently-executing
    For eclipse user with unittest or debugger, the function search for the correct folder in the stack
    You can pass __file__ (with 4 underscores) if you want the caller directory
    """
    # If we don't have the __file__ :
    if _file_ is None:
        # We get the last :
        rootFile = inspect.stack()[-1][1]
        folder = os.path.abspath(rootFile)
        # If we use unittest :
        if ("/pysrc" in folder) & ("org.python.pydev" in folder):
            previous = None
            # We search from left to right the case.py :
            for el in inspect.stack():
                currentFile = os.path.abspath(el[1])
                if ("unittest/case.py" in currentFile) | ("org.python.pydev" in currentFile):
                    break
                previous = currentFile
            folder = previous
        # We return the folder :
        return os.path.dirname(folder)
    else:
        # We return the folder according to specified __file__ :
        return os.path.dirname(os.path.realpath(_file_))

أبسط طريقة هي:

في script_1.py:

import subprocess
subprocess.call(['python3',<path_to_script_2.py>])

في script_2.py:

sys.argv[0]

ملاحظة.:لقد حاولت execfile, ، ولكن نظرًا لأنه يقرأ script_2.py كسلسلة، sys.argv[0] عاد <string>.

لقد استخدمت دائمًا ميزة نظام التشغيل في دليل العمل الحالي، أو CWD.هذا جزء من المكتبة القياسية، وهو سهل التنفيذ للغاية.هنا مثال:

    import os
    base_directory = os.getcwd()

تمت كتابة معظم هذه الإجابات في إصدار Python 2.x أو إصدار سابق.في Python 3.x، تغير بناء جملة وظيفة الطباعة ليتطلب الأقواس، أي.مطبعة().

إذن، هذه الإجابة السابقة ذات النتيجة العالية من user13993 في Python 2.x:

import inspect, os
print inspect.getfile(inspect.currentframe()) # script filename (usually with path)
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # script directory

يصبح في بايثون 3.x:

import inspect, os
print(inspect.getfile(inspect.currentframe())) # script filename (usually with path)
print(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) ) # script directory

إذا كنت تريد فقط اسم الملف بدون ./ أو .py يمكنك تجربة هذا

filename = testscript.py
file_name = __file__[2:-3]

file_name سوف تقوم بطباعة TestScript ، يمكنك إنشاء ما تريده عن طريق تغيير الفهرس داخل [

import os

import wx


# return the full path of this file
print(os.getcwd())

icon = wx.Icon(os.getcwd() + '/img/image.png', wx.BITMAP_TYPE_PNG, 16, 16)

# put the icon on the frame
self.SetIcon(icon)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top