515

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

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

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

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

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

4

30 回答 30

591
__file__

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

import os

os.path.realpath(__file__)
于 2009-12-23T20:33:47.133 回答
273

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
于 2008-09-08T23:02:42.043 回答
97

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 fooimport 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(还尝试了具有绝对路径的 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
于 2015-08-06T22:50:01.307 回答
74

我认为这更清洁:

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

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

print inspect.getfile(inspect.currentframe())

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

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

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

于 2011-07-08T17:50:28.897 回答
48
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
于 2015-02-06T01:05:18.657 回答
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]
于 2010-02-26T22:25:29.397 回答
17

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

from pathlib import Path

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

如果您正在寻找当前文件的目录,则只需添加语句.parent即可:Path()

current_path: Path = Path(__file__).parent.resolve()
于 2019-08-23T19:19:43.533 回答
15

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

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

加载模块的文件,如果它是从文件加载的

于 2008-09-08T19:42:56.920 回答
14
import os
print os.path.basename(__file__)

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

于 2013-08-11T03:05:05.107 回答
12

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

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

这是一个很老套的决定。但它不需要外部库,这对我来说是最重要的。

于 2012-08-08T09:42:27.620 回答
10

试试这个,

import os
os.path.dirname(os.path.realpath(__file__))
于 2019-02-22T17:31:38.173 回答
8

__file__属性适用于包含主要执行代码的文件以及导入的模块。

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

于 2008-09-08T19:56:19.730 回答
8
import os
os.path.dirname(os.path.abspath(__file__))

无需检查或任何其他库。

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

于 2014-06-24T15:04:34.567 回答
7
import sys

print sys.path[0]

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

于 2010-01-02T18:34:55.573 回答
5

我认为这只是__file__ 听起来您可能还想检查检查模块

于 2008-09-08T19:44:07.433 回答
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'
于 2008-09-09T00:00:52.887 回答
3
import sys
print sys.argv[0]
于 2010-04-19T07:47:21.700 回答
2

这应该有效:

import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
于 2015-06-14T16:37:44.943 回答
2
print(__file__)
print(__import__("pathlib").Path(__file__).parent)
于 2019-05-05T01:19:50.733 回答
2

这是我使用的,所以我可以毫无问题地将我的代码扔到任何地方。__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__))
于 2019-06-28T01:28:38.270 回答
1

获取执行脚本的目录

 print os.path.dirname( inspect.getfile(inspect.currentframe()))
于 2017-05-10T10:51:15.587 回答
0

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

sys._getframe().f_code.co_filename

于 2011-03-01T09:23:09.230 回答
0

我写了一个函数,它考虑到了 eclipse debuggerunittest。它返回您启动的第一个脚本的文件夹。您可以选择指定__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_))
于 2016-06-14T15:06:50.273 回答
0

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

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

于 2018-04-12T05:19:36.633 回答
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>.

于 2018-06-08T12:29:47.303 回答
0

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

    import os
    base_directory = os.getcwd()
于 2019-01-23T16:31:44.130 回答
0

以下返回当前主脚本所在的路径。我用 Linux、Win10、IPython 和 Jupyter Lab 对此进行了测试。我需要一个也适用于本地 Jupyter 笔记本的解决方案。

import builtins
import os
import sys

def current_dir():
    if "get_ipython" in globals() or "get_ipython" in dir(builtins):
        # os.getcwd() is PROBABLY the dir that hosts the active notebook script.
        # See also https://github.com/ipython/ipython/issues/10123
        return os.getcwd()
    else:
        return os.path.abspath(os.path.dirname(sys.argv[0]))
于 2022-01-19T15:14:23.537 回答
-2

这些答案大部分是用 Python 2.x 或更早版本编写的。在 Python 3.x 中,打印函数的语法已更改为需要括号,即 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
于 2018-11-09T01:15:45.260 回答
-3

如果你只想要没有文件名,./或者.py你可以试试这个

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

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

于 2013-01-20T20:52:13.340 回答
-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)
于 2013-01-24T02:43:09.633 回答