如何获取当前正在执行的文件的路径和名称?


482

我有调用其他脚本文件的脚本,但是我需要获取该进程中当前正在运行的文件的文件路径。

例如,假设我有三个文件。使用execfile

  • script_1.py来电script_2.py
  • 依次script_2.py调用script_3.py

我怎样才能获得的文件名和路径script_3.py从内部代码script_3.py,而无需从传递这些信息作为参数script_2.py

(执行os.getcwd()将返回原始启动脚本的文件路径,而不是当前文件的路径。)



2
os.path.realpath(file
Girish Gupta

Answers:


256

p1.py:

execfile("p2.py")

p2.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

11
注意:在不同的环境下,此调用不会产生相同的结果。考虑接受以下Usagi的答案:stackoverflow.com/a/6628348/851398
法拉第2014年

3
@faraday:您能举个例子吗?我已经回答了使用类似的问题inspect.getabsfile(),它适用于我尝试过的所有情况。
jfs

1
确实@Usagi回答更好吗?
Dror 2014年

4
nah user13993的定位效果要好得多
osirisgothra

6
user13993确实钉住了它。应该是os.path.realpath(__file__)
uchuugaka

565
__file__

正如其他人所说。您可能还想使用os.path.realpath消除符号链接:

import os

os.path.realpath(__file__)

14
需要注意这种方法,因为有时__file__返回“ script_name.py”,有时返回“ script_name.pyc”。因此输出不稳定。
mechatroner's

27
但是,由于我们仅使用此文件的路径,因此不相关。
Uwe Koloska '16

5
这很奇怪:在命令行 "__file__"中使用引号(作为字符串)运行时,__file__ 会给出运行cmd的目录,但是(不带引号则是源文件的路径...这是为什么
muon

7
@muon不会检查传入的文件名字符串是否存在,并且由于文件路径是相对于cwd的,因此该os.path.realpath函数假定dir路径的一部分是存在的。 os.path.dirname(os.path.realpath(__file__))返回带有文件的目录。os.path.dirname(os.path.realpath("__file__"))返回cwd。os.path.dirname(os.path.realpath("here_be_dragons"))还返回cwd。
Jamie Bull '18

86

更新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文件添加到两个文件夹中即可。

对于Python 3,execfile不存在-最接近的替代方法是exec(open(<filename>).read()),尽管这会影响堆栈框架。使用起来最简单,import foo而且import lib.bar-无需__init__.py文件。

另请参见import和execfile之间的区别


原始答案:

这是基于该线程答案的实验-Windows上的Python 2.7.10。

基于堆栈的堆栈似乎是唯一可以提供可靠结果的堆栈。后两个语法最短,即-

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(也尝试了具有绝对路径并从另一个文件夹调用的execfile)。

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

72

我认为这更干净:

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

并获得与以下信息相同的信息:

print inspect.getfile(inspect.currentframe())

其中[0]是堆栈中的当前帧(堆栈的顶部),[1]是文件名,请增加以在堆栈中向后移动,即

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

将是调用当前框架的脚本的文件名。另外,使用[-1]将使您到达堆栈的底部,即原始调用脚本。


4
不建议依靠元组内部的位置。根本不清楚您在读取代码时要获取哪些数据。
jpmc26

5
inspect.getfile()__file__如果传递了模块对象,则返回属性。inspect.currentframe()返回模块。嗯,这是一种昂贵的说法__file__
马丁·彼得斯

inspect.stack()是一个非常昂贵的函数,而不仅仅是inspect.currentframe(),它还调用inspect.getfile()模块对象。
马丁·彼得斯

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

1
我刚刚尝试了@Pat Notz的评论。我认为您可以通过来获取文件名__file__
hlin117

在Python3中,os.path.dirname将为您提供运行脚本的相对路径。例如,在python ../../test.pyos.path.dirname../../,而不是绝对路径的脚本。我一直在寻找abspath,但删除了脚本的名称。sys.path的第一个元素显然是答案sys.path[0]
aerijman

37

如果您的脚本仅包含一个文件,则标记为“最佳”的建议都是正确的。

如果要从可能作为模块导入的文件中找出可执行文件的名称(即,传递给当前程序的python解释器的根文件),则需要执行此操作(假设此文件位于文件中)名为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]

它很好用,但是不能在Eclipse上进行单元测试,我得到了/home/user/Softwares/eclipse/plugins/org.python.pydev_4.5.5.201603221110/pysrc
hayj 2016年

2
sys.modules['__main__'].__file__确实,这是一种昂贵的拼写方式。
马丁·彼得斯

14
import os
print os.path.basename(__file__)

这只会给我们文件名。即如果文件的绝对路径为c:\ abcd \ abc.py,则第二行将打印abc.py


14

您还不清楚“进程中当前正在运行的文件的文件路径”是什么意思。 sys.argv[0]通常包含由Python解释器调用的脚本的位置。查看sys文档以获取更多详细信息。

正如@Tim和@Pat Notz指出的那样,__file__属性提供了对

从模块加载文件的文件(如果从文件加载的文件)


1
当我们将python程序传递给win32 exe时,“ print os.path.abspath(file)”和“ print inspect.getfile(inspect.currentframe())”不起作用。仅sys.argv [0]有效!:)但您只会得到名字!
aF。

11

我有一个必须在Windows环境下工作的脚本。这段代码是我完成的:

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

这是一个不明智的决定。但这不需要外部库,这对我来说是最重要的。


1
为此,我必须“导入os,sys”,但到目前为止,这是最好的答案,它实际上仅返回字符串末尾没有文件名的路径。
emmagras 2014年


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

无需检查或任何其他库。

当我必须导入脚本(从与执行脚本所在的目录不同的目录)导入脚本时,此方法对我有用,该脚本使用与导入脚本位于同一文件夹中的配置文件。


如果当前工作目录(os.getcwd)与文件所在的目录不同,则将无法产生所需的答案。
铁枕头

2
为何如此?在这种情况下对我来说很好。我得到的文件所在的目录。
迈克尔Mior

@IronPillow也许这个答案将帮助您满足您的需求。stackoverflow.com/a/41546830/3123191
Kwuite


6
import sys

print sys.path[0]

这将打印当前正在执行的脚本的路径


2
sys.path [0]非常有用,但是提供了script1的路径,而不是请求的script3的路径
James

至少在OS X(2.7版)上,我认为这没有可靠的作用。如果直接执行相同的文件,它将起作用。从repl不能正常工作,特别是从进口的鸡蛋中无法工作
uchuugaka


4

您可以使用 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'

4

由于Python 3相当主流,因此我想提供一个pathlib答案,因为我认为它现在可能是访问文件和路径信息的更好工具。

from pathlib import Path

current_file: Path = Path(__file__).resolve()

如果要查找当前文件的目录,则只需添加.parent以下Path()语句即可:

current_path: Path = Path(__file__).parent.resolve()

3
import sys
print sys.argv[0]

10
不幸的是,这仅在使用完整路径调用脚本时才有效,因为它仅在命令行上返回“第一个参数”,即对脚本的调用。
cregox

2

这应该工作:

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

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

4
不鼓励仅使用代码的答案。请添加一些有关如何解决问题或与现有答案有何不同的解释。From
尼克

1

获取执行脚本的目录

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

1

我一直只使用“当前工作目录”或CWD的os功能。这是标准库的一部分,非常容易实现。这是一个例子:

    import os
    base_directory = os.getcwd()

1
您能否修改答案,使其适用于提出的问题?此答案不适用于“我如何获取当前正在执行的文件的路径和名称 ”的问题
Marco

1
这给出了运行python命令的路径。因此,当您python script.py在已经存在的同一文件夹中运行命令时,它似乎可以工作,而实际上与pwd在Linux上运行时相同。
乔治,

0

我在__file__中使用了此方法,
os.path.abspath(__file__)
但是有一个小技巧,它在第一次运行代码时返回.py文件,下一次运行给出* .pyc文件的名称,
所以我使用:
inspect.getfile(inspect.currentframe())

sys._getframe().f_code.co_filename


0

我编写了一个函数,该函数考虑了Eclipse 调试器unittest。它返回您启动的第一个脚本的文件夹。您可以选择指定__file__ 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_))

0

要保持跨平台(macOS / Windows / Linux)的迁移一致性,请尝试:

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


2
错了 这将为您提供当前路径,而不是当前文件的路径。
查尔斯·普拉格

0

最简单的方法是:

script_1.py中:

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

script_2.py中:

sys.argv[0]

PS:我已经尝试过execfile,但是由于它以字符串形式读取script_2.py,所以sys.argv[0]返回了<string>


0

这是我所使用的,因此我可以将我的代码无处不在。__name__总是被定义,但是__file__仅当代码作为文件运行时才被定义(例如,不在IDLE / iPython中)。

    if '__file__' in globals():
        self_name = globals()['__file__']
    elif '__file__' in locals():
        self_name = locals()['__file__']
    else:
        self_name = __name__

或者,可以这样写:

self_name = globals().get('__file__', locals().get('__file__', __name__))

-2

这些答案大多数都是用Python 2.x或更早版本编写的。在Python 3.x中,print函数的语法已更改为需要括号,即print()。

因此,Python 2.x中来自user13993的较早的高分答案:

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

在Python 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

-3

如果您只想要文件名而没有,./或者.py可以尝试此操作

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

file_name 将打印测试脚本,您可以通过更改[]中的索引来生成所需的任何内容


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

7
os.getcwd()返回过程的当前WORKING目录,而不是当前正在执行的文件的目录。这似乎可以返回正确的结果,但是在许多情况下,结果将不是当前文件的父目录。如上建议使用os.path.dirname(file)更好。
samaspin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.