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

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

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

  • script_1.py调用script_2.py
  • 然后,script_2.py调用script_3.py

我怎么能得到文件名和路径的script_3.py从代码script_3.py,而不必通过信息作为参数从script_2.py?

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

590917 次浏览
你所说的“当前在进程中运行的文件的文件路径”是什么意思并不完全清楚。 sys.argv[0]通常包含Python解释器调用的脚本的位置。 查看sys文件查看更多细节

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

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

文件加载

我认为它只是__file__听起来你可能也想签出检查模块

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

看到# EYZ0

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

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

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

import os


os.path.realpath(__file__)
import sys


print sys.path[0]

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

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

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

# EYZ0

# EYZ0

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

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

  • # EYZ0
  • # EYZ0
  • # EYZ0
import sys
print sys.argv[0]
我使用了__file__
的方法 # EYZ0 < br > 但是有一个小技巧,它返回。py文件 当代码第一次运行时, 下一个运行的名称为*。佩克文件< br > 所以我选择了
# EYZ0 < br > 或< br > # EYZ0 < / p >

我觉得这个比较干净:

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

得到的信息与:

print inspect.getfile(inspect.currentframe())

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

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

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

我有一个脚本,必须在windows环境下工作。 这段代码剪辑是什么我已经完成:

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

这是个很俗气的决定。但它不需要外部库,这是我的情况下最重要的事情。

import os
print os.path.basename(__file__)

这将只给我们文件名。例如,如果文件的abspath是c:\abcd\abc.py,那么第二行将打印abc.py

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

不需要检查或任何其他图书馆。

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

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,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))

更新2018-11-28:

下面是Python 2和3的实验总结。与

main.py -运行foo.py
.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运行main.py(也尝试过使用绝对路径的execfiles,并从单独的文件夹中调用)。

< p > C: \ filepaths \ main.py: # EYZ0 < br > C: \ filepaths \ foo.py: # EYZ0 < br > C: \ filepaths \ lib \ bar.py: < / p >
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
我写了一个函数,其中考虑到eclipse 调试器unittest。 它返回您启动的第一个脚本的文件夹。你可以选择指定__file__变量,但最主要的是你不必在所有的调用层次结构中共享这个变量

也许你可以处理一些我没见过的特殊情况,但对我来说是可以的。

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

获取执行脚本的目录

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

最简单的方法是:

在# EYZ0

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

在# EYZ0

sys.argv[0]

附注:我尝试过execfile,但由于它读取script_2.py作为字符串,sys.argv[0]返回<string>

试试这个,

import os
os.path.dirname(os.path.realpath(__file__))
print(__file__)
print(__import__("pathlib").Path(__file__).parent)

这是我使用的,所以我可以把我的代码扔到任何地方而没有问题。__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__))

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

from pathlib import Path


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

如果你正在寻找当前文件的目录,它就像添加.parentPath()语句一样简单:

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

下面返回当前主脚本所在的路径。我用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]))