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

 2019-04-22 

How do I get the path and name of the file that is currently executing?

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

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

  • script_1.py调用script_2.py
  • 反过来,script_2.py调用script_3.py

如何从script_3.py内的代码中获取script_3.py的文件名和路径,而不必将该信息作为script_2.py的参数传递?

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


1
__file__

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

1
2
3
import os

os.path.realpath(__file__)


P1.PY:

1
execfile("p2.py")

P2.PY:

1
2
3
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


更新2018-11-28:

下面是对Python2和3的实验的总结。用

main.py-运行foo.pyfoo.py-运行lib/bar.pylib/bar.py-打印文件路径表达式

1
2
3
4
5
6
| 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().read()),尽管这会影响堆栈帧。只使用import fooimport lib.bar是最简单的,不需要__init__.py文件。

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

原始答案:

下面是一个基于这个线程中答案的实验-在Windows上使用python 2.7.10。

基于堆栈的是唯一看起来能给出可靠结果的。最后两个语法最短,即-

1
2
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

基于以下三个文件,并使用python main.py从其文件夹运行main.py(还尝试使用绝对路径的execfiles并从单独的文件夹调用)。

C:filepathsmain.py:execfile('foo.py')。C:filepathsfoo.py:execfile('lib/bar.py')。C:filepathslibar.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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

我觉得这比较干净:

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

得到的信息与:

1
print inspect.getfile(inspect.currentframe())

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

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

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


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


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

如果要从一个可能作为模块导入的文件中查找可执行文件(即当前程序传递给python解释器的根文件)的名称,则需要执行此操作(假设该文件位于名为foo.py的文件中):

import inspect

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

因为栈上的最后一件事([-1]是进入栈中的第一件事(栈是lifo/filo数据结构)。

然后,在file bar.py中,如果您使用cx1(7),它将打印bar.py,而不是foo.py,这将是所有这些的值:

  • __file__
  • inspect.getfile(inspect.currentframe())
  • inspect.stack()[0][1]


1
2
import os
print os.path.basename(__file__)

这将只提供文件名。例如,如果文件的abspath为c:abcd abc.py,则第二行将打印abc.py。


不完全清楚您所说的"当前在进程中运行的文件的文件路径"是什么意思。sys.argv[0]通常包含由Python解释器调用的脚本的位置。有关详细信息,请参阅sys文档。

正如@tim和@pat notz指出的,文件属性提供对

the file from which the module was
loaded, if it was loaded from a file


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

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

这是一个愚蠢的决定。但它不需要外部的库,在我的例子中它是最重要的。


__file__属性既适用于包含主执行代码的文件,也适用于导入的模块。

请参阅https://web.archive.org/web/20090918095828/http://pyref.infogami.com//uuuu文件__


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

不需要检查或任何其他库。

当我必须导入一个脚本(从另一个目录,然后是执行的脚本)时,这对我很有效,该脚本使用的配置文件与导入的脚本位于同一个文件夹中。


1
2
3
import sys

print sys.path[0]

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


我认为这只是__file__的声音,你可能还想检查模块。


您可以使用inspect.stack()

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


1
2
import sys
print sys.argv[0]


这应该有效:

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

获取执行脚本的目录

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

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

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


试试这个,

1
2
import os
os.path.dirname(os.path.realpath(__file__))


我编写了一个函数,考虑到Eclipse调试器和UnitTest。它返回您启动的第一个脚本的文件夹。您可以选择指定_uu文件_uuuvar,但主要的是您不必在所有调用层次结构中共享这个变量。

也许你可以处理别人堆积的一些我没看到的特殊案件,但对我来说没关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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_))

我用了带文件的方法__os.path.abspath(__file__)但是有一个小技巧,它返回.py文件当代码第一次运行时,下一次运行给出*.pyc文件的名称所以我留下来:inspect.getfile(inspect.currentframe())sys._getframe().f_code.co_filename


最简单的方法是:

在Script Pt1.Py中:

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

在Script Pt2.Py中:

1
sys.argv[0]

附言:我试过execfile,但自从它把script_2.py读成字符串后,sys.argv[0]返回


我一直在使用当前工作目录的操作系统功能,即cwd。这是标准库的一部分,非常容易实现。下面是一个例子:

1
2
    import os
    base_directory = os.getcwd()


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

所以,在python 2.x中,用户13993给出了这个早期的高分答案:

1
2
3
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中:

1
2
3
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


1
2
3
4
5
6
7
8
9
10
11
12
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)


如果只需要不带./.py的文件名,可以尝试此操作

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

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