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

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

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

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

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

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

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

I have scripts calling other script files but I need to get the filepath of the file that is currently running within the process.

For example, let’s say I have three files. Using execfile:

  • script_1.py calls script_2.py.
  • In turn, script_2.py calls script_3.py.

How can I get the file name and path of script_3.py, from code within script_3.py, without having to pass that information as arguments from script_2.py?

(Executing os.getcwd() returns the original starting script’s filepath not the current file’s.)


回答 0

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

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

回答 1

__file__

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

import os

os.path.realpath(__file__)
__file__

as others have said. You may also want to use os.path.realpath to eliminate symlinks:

import os

os.path.realpath(__file__)

回答 2

更新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

Update 2018-11-28:

Here is a summary of experiments with Python 2 and 3. With

main.py – runs foo.py
foo.py – runs lib/bar.py
lib/bar.py – prints filepath expressions

| 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__                               |

For Python 2, it might be clearer to switch to packages so can use from lib import bar – just add empty __init__.py files to the two folders.

For Python 3, execfile doesn’t exist – the nearest alternative is exec(open(<filename>).read()), though this affects the stack frames. It’s simplest to just use import foo and import lib.bar – no __init__.py files needed.

See also Difference between import and execfile


Original Answer:

Here is an experiment based on the answers in this thread – with Python 2.7.10 on Windows.

The stack-based ones are the only ones that seem to give reliable results. The last two have the shortest syntax, i.e. –

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

Here’s to these being added to sys as functions! Credit to @Usagi and @pablog

Based on the following three files, and running main.py from its folder with python main.py (also tried execfiles with absolute paths and calling from a separate folder).

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

回答 3

我认为这更干净:

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

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

print inspect.getfile(inspect.currentframe())

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

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

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

I think this is cleaner:

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

and gets the same information as:

print inspect.getfile(inspect.currentframe())

Where [0] is the current frame in the stack (top of stack) and [1] is for the file name, increase to go backwards in the stack i.e.

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

would be the file name of the script that called the current frame. Also, using [-1] will get you to the bottom of the stack, the original calling script.


回答 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
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only

回答 5

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

如果要从可能作为模块导入的文件中找出可执行文件的名称(即,传递给当前程序的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]

The suggestions marked as best are all true if your script consists of only one file.

If you want to find out the name of the executable (i.e. the root file passed to the python interpreter for the current program) from a file that may be imported as a module, you need to do this (let’s assume this is in a file named foo.py):

import inspect

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

Because the last thing ([-1]) on the stack is the first thing that went into it (stacks are LIFO/FILO data structures).

Then in file bar.py if you import foo it’ll print bar.py, rather than foo.py, which would be the value of all of these:

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

回答 6

import os
print os.path.basename(__file__)

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

import os
print os.path.basename(__file__)

this will give us the filename only. i.e. if abspath of file is c:\abcd\abc.py then 2nd line will print abc.py


回答 7

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

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

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

It’s not entirely clear what you mean by “the filepath of the file that is currently running within the process”. sys.argv[0] usually contains the location of the script that was invoked by the Python interpreter. Check the sys documentation for more details.

As @Tim and @Pat Notz have pointed out, the __file__ attribute provides access to

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


回答 8

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

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

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

I have a script that must work under windows environment. This code snipped is what I’ve finished with:

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

it’s quite a hacky decision. But it requires no external libraries and it’s the most important thing in my case.


回答 9

尝试这个,

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

Try this,

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

回答 10

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

无需检查或任何其他库。

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

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

No need for inspect or any other library.

This worked for me when I had to import a script (from a different directory then the executed script), that used a configuration file residing in the same folder as the imported script.


回答 11

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

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

The __file__ attribute works for both the file containing the main execution code as well as imported modules.

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


回答 12

import sys

print sys.path[0]

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

import sys

print sys.path[0]

this would print the path of the currently executing script


回答 13

我认为这__file__ 听起来像您可能还想签出inspect模块

I think it’s just __file__ Sounds like you may also want to checkout the inspect module.


回答 14

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

You can use 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'

回答 15

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

from pathlib import Path

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

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

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

Since Python 3 is fairly mainstream, I wanted to include a pathlib answer, as I believe that it is probably now a better tool for accessing file and path information.

from pathlib import Path

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

If you are seeking the directory of the current file, it is as easy as adding .parent to the Path() statement:

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

回答 16

import sys
print sys.argv[0]
import sys
print sys.argv[0]

回答 17

这应该工作:

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

This should work:

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

回答 18

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

回答 19

获取执行脚本的目录

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

To get directory of executing script

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

回答 20

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

    import os
    base_directory = os.getcwd()

I have always just used the os feature of Current Working Directory, or CWD. This is part of the standard library, and is very easy to implement. Here is an example:

    import os
    base_directory = os.getcwd()

回答 21

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

sys._getframe().f_code.co_filename

I used the approach with __file__
os.path.abspath(__file__)
but there is a little trick, it returns the .py file when the code is run the first time, next runs give the name of *.pyc file
so I stayed with:
inspect.getfile(inspect.currentframe())
or
sys._getframe().f_code.co_filename


回答 22

我编写了一个函数,该函数考虑了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_))

I wrote a function which take into account eclipse debugger and unittest. It return the folder of the first script you launch. You can optionally specify the __file__ var, but the main thing is that you don’t have to share this variable across all your calling hierarchy.

Maybe you can handle others stack particular cases I didn’t see, but for me it’s ok.

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

回答 23

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

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

To keep the migration consistency across platforms (macOS/Windows/Linux), try:

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


回答 24

最简单的方法是:

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>

Simplest way is:

in script_1.py:

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

in script_2.py:

sys.argv[0]

P.S.: I’ve tried execfile, but since it reads script_2.py as a string, sys.argv[0] returned <string>.


回答 25

这是我所使用的,因此我可以将我的代码无处不在。__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__))

Here is what I use so I can throw my code anywhere without issue. __name__ is always defined, but __file__ is only defined when the code is run as a file (e.g. not in IDLE/iPython).

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

Alternatively, this can be written as:

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

回答 26

这些答案大多数都是用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

Most of these answers were written in Python version 2.x or earlier. In Python 3.x the syntax for the print function has changed to require parentheses, i.e. print().

So, this earlier high score answer from user13993 in 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

Becomes in 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

回答 27

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

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

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

if you want just the filename without ./ or .py you can try this

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

file_name will print testscript you can generate whatever you want by changing the index inside []


回答 28

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