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

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

Script_1.py调用script_2.py。 反过来,script_2.py调用script_3.py。

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

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


当前回答

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

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

其他回答

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

如果你想从一个可能作为模块导入的文件中找到可执行文件的名称(即传递给当前程序的python解释器的根文件),你需要这样做(让我们假设这是在一个名为foo.py的文件中):

进口检查

打印inspect.stack () [1] [1]

因为堆栈上的最后一个东西([-1])是进入堆栈的第一个东西(堆栈是LIFO/FILO数据结构)。

然后在bar.py文件中,如果你导入foo,它会打印bar.py,而不是foo.py,这将是所有这些的值:

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

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
print(__file__)
print(__import__("pathlib").Path(__file__).parent)

更新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。不需要__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

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

C: \ filepaths玩. py execfile (foo . py”) C: \ filepaths foo . py execfile(“lib /酒吧. py”) C:李勃filepaths \ \ . 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
__file__

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

import os

os.path.realpath(__file__)