如何获取当前正在执行的python文件的路径和名称?
- 2024-11-28 08:38:00
- admin 原创
- 272
问题描述:
我有调用其他脚本文件的脚本,但我需要获取当前在进程中运行的文件的文件路径。
例如,假设我有三个文件。使用execfile:
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来消除符号链接:
import os
os.path.realpath(__file__)
解决方案 2:
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
解决方案 3:
更新2018-11-28:
以下是对 Python 2 和 Python 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:ilepathslibar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:ilepathslib
这些被添加到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:ilepaths
print
print os.path.realpath(__file__) # C:ilepathsmain.py
print os.path.abspath(__file__) # C:ilepathsmain.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:ilepaths
print os.path.abspath(os.path.split(sys.argv[0])[0]) # C:ilepaths
print os.path.dirname(os.path.abspath(__file__)) # C:ilepaths
print os.path.dirname(os.path.realpath(sys.argv[0])) # C:ilepaths
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:ilepathslibar.py
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:ilepathslib
print
print os.path.abspath(inspect.stack()[0][1]) # C:ilepathslibar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:ilepathslib
print
解决方案 4:
我认为这更干净:
import inspect
print inspect.stack()[0][1]
并获得与以下相同的信息:
print inspect.getfile(inspect.currentframe())
其中 [0] 是堆栈中的当前帧(堆栈顶部),[1] 是文件名,增加可在堆栈中向后移动,即
print inspect.stack()[1][1]
将是调用当前帧的脚本的文件名。此外,使用 [-1] 将带您到达堆栈底部,即原始调用脚本。
解决方案 5:
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
解决方案 6:
由于 Python 3 相当主流,我想包含一个pathlib
答案,因为我相信它现在可能是访问文件和路径信息的更好的工具。
from pathlib import Path
current_file: Path = Path(__file__).resolve()
如果要查找当前文件的目录,只需添加.parent
以下Path()
语句即可:
current_path: Path = Path(__file__).parent.resolve()
解决方案 7:
如果您的脚本仅包含一个文件,则标记为最佳的建议都是正确的。
如果您想从可能作为模块导入的文件中找到可执行文件的名称(即传递给当前程序的 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]
解决方案 8:
不太清楚您所说的“当前在进程中运行的文件的文件路径”是什么意思。sys.argv[0]
通常包含 Python 解释器调用的脚本的位置。查看sys 文档以了解更多详细信息。
正如 @Tim 和 @Pat Notz 指出的那样,__file__ 属性可以访问
如果模块是从文件加载的,则从中加载模块的文件
解决方案 9:
import os
print os.path.basename(__file__)
这将仅给我们文件名。例如,如果文件的绝对路径是 c:\abcd\abc.py,那么第二行将打印 abc.py
解决方案 10:
试试这个,
import os
os.path.dirname(os.path.realpath(__file__))
解决方案 11:
我有一个必须在 Windows 环境下运行的脚本。这段代码是我完成的:
import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
这是个相当不明智的决定。但它不需要任何外部库,而这对我来说是最重要的。
解决方案 12:
import os
os.path.dirname(os.path.abspath(__file__))
无需检查或任何其他库。
当我必须导入一个脚本(来自与执行的脚本不同的目录)时,这对我有用,该脚本使用与导入的脚本位于同一文件夹中的配置文件。
解决方案 13:
该__file__
属性适用于包含主执行代码的文件以及导入的模块。
参见https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__
解决方案 14:
import sys
print sys.path[0]
这将打印当前正在执行的脚本的路径
解决方案 15:
我认为听起来__file__
您可能还想检查检查模块。
解决方案 16:
您可以使用inspect.stack()
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'
解决方案 17:
import sys
print sys.argv[0]
解决方案 18:
这应该有效:
import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
解决方案 19:
print(__file__)
print(__import__("pathlib").Path(__file__).parent)
解决方案 20:
这是我使用的,以便我可以将代码放在任何地方而不会出现问题。__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__))
解决方案 21:
获取执行脚本的目录
print os.path.dirname( inspect.getfile(inspect.currentframe()))
解决方案 22:
我想做得更好,因为我需要更多信息。获取方法如下:
正在运行的脚本的完整路径
脚本目录
脚本的基本文件名
不带扩展名的文件名
脚本的扩展
运行脚本的用户的主目录
脚本所在用户的主目录
来自我的eRCaGuy_hello_world仓库中的get_script_path.py:
import os
import sys
FULL_PATH_TO_SCRIPT = os.path.abspath(__file__)
SCRIPT_DIRECTORY = str(os.path.dirname(FULL_PATH_TO_SCRIPT))
SCRIPT_PARENT_DIRECTORY = str(os.path.dirname(SCRIPT_DIRECTORY))
# this also works, but its output will have the two dots (`/..`) in it.
SCRIPT_PARENT_DIRECTORY2 = f"{SCRIPT_DIRECTORY}/.."
FILENAME = str(os.path.basename(FULL_PATH_TO_SCRIPT))
FILENAME_NO_EXTENSION = os.path.splitext(FILENAME)[0]
FILENAME_EXTENSION = os.path.splitext(FILENAME)[1]
# the full path to the executable script being run
EXECUTABLE_FULL_PATH = sys.argv[0]
# the name of the executable being run
EXECUTABLE_NAME = os.path.basename(EXECUTABLE_FULL_PATH)
# Other useful paths:
# home directory of the current, running user
HOME_DIR_USER = os.path.expanduser("~")
# Obtain the home dir of the user in whose home directory this script resides,
# which may *not* be the home dir of the current user! Ex: run this script
# as root, via `sudo`, and you'll see that `HOME_DIR_USER` != `HOME_DIR_SCRIPT`.
script_path_list = os.path.normpath(FULL_PATH_TO_SCRIPT).split(os.sep)
HOME_DIR_SCRIPT = os.path.join("/", script_path_list[1], script_path_list[2])
# Bonus: add the parent directory to the start of the system PATH variable so
# that you can import modules directly in that directory above this script!
sys.path.insert(0, SCRIPT_PARENT_DIRECTORY)
# Now, assuming there is a `config.py`` file in the `SCRIPT_PARENT_DIRECTORY`,
# you can import it directly, like this:
#
# import config.py
#
# Print results
print(f"__file__: {__file__}")
print(f"FULL_PATH_TO_SCRIPT: {FULL_PATH_TO_SCRIPT}")
print(f"SCRIPT_DIRECTORY: {SCRIPT_DIRECTORY}")
print(f"SCRIPT_PARENT_DIRECTORY: {SCRIPT_PARENT_DIRECTORY}")
print(f"SCRIPT_PARENT_DIRECTORY2: {SCRIPT_PARENT_DIRECTORY2}")
print(f"FILENAME: {FILENAME}")
print(f"FILENAME_NO_EXTENSION: {FILENAME_NO_EXTENSION}")
print(f"FILENAME_EXTENSION: {FILENAME_EXTENSION}")
print("---")
print(f"HOME_DIR_USER: {HOME_DIR_USER}")
print(f"script_path_list: {script_path_list}")
print(f"HOME_DIR_SCRIPT: {HOME_DIR_SCRIPT}")
示例运行和输出,在 Linux Ubuntu 20.04 和 22.04 上测试:
eRCaGuy_hello_world$ python/get_script_path.py
__file__: python/get_script_path.py
FULL_PATH_TO_SCRIPT: /home/gabriel/GS/dev/eRCaGuy_hello_world/python/get_script_path.py
SCRIPT_DIRECTORY: /home/gabriel/GS/dev/eRCaGuy_hello_world/python
SCRIPT_PARENT_DIRECTORY: /home/gabriel/GS/dev/eRCaGuy_hello_world
SCRIPT_PARENT_DIRECTORY2: /home/gabriel/GS/dev/eRCaGuy_hello_world/python/..
FILENAME: get_script_path.py
FILENAME_NO_EXTENSION: get_script_path
FILENAME_EXTENSION: .py
---
HOME_DIR_USER: /home/gabriel
script_path_list: ['', 'home', 'gabriel', 'GS', 'dev', 'eRCaGuy_hello_world', 'python', 'get_script_path.py']
HOME_DIR_SCRIPT: /home/gabriel
以 root 身份运行时:请注意HOME_DIR_USER
,活动用户的主目录现在发生变化:
eRCaGuy_hello_world$ sudo python/get_script_path.py
[sudo] password for gabriel:
__file__: python/get_script_path.py
FULL_PATH_TO_SCRIPT: /home/gabriel/GS/dev/eRCaGuy_hello_world/python/get_script_path.py
SCRIPT_DIRECTORY: /home/gabriel/GS/dev/eRCaGuy_hello_world/python
SCRIPT_PARENT_DIRECTORY: /home/gabriel/GS/dev/eRCaGuy_hello_world
SCRIPT_PARENT_DIRECTORY2: /home/gabriel/GS/dev/eRCaGuy_hello_world/python/..
FILENAME: get_script_path.py
FILENAME_NO_EXTENSION: get_script_path
FILENAME_EXTENSION: .py
---
HOME_DIR_USER: /root
script_path_list: ['', 'home', 'gabriel', 'GS', 'dev', 'eRCaGuy_hello_world', 'python', 'get_script_path.py']
HOME_DIR_SCRIPT: /home/gabriel
发现的附加说明HOME_DIR_SCRIPT
...这是您的 Python 脚本所在路径的主目录。
如果您的脚本的路径是/home/gabriel/GS/dev/eRCaGuy_dotfiles/useful_scripts/cpu_logger.py
,并且您希望获取该路径的主目录部分,即/home/gabriel
,您可以执行以下操作:
import os
# Obtain the home dir of the user in whose home directory this script resides
script_path_list = os.path.normpath(os.path.abspath(__file__)).split(os.sep)
home_dir = os.path.join("/", script_path_list[1], script_path_list[2])
为了帮助理解这一点,以下是 、 和 的路径os.path.abspath(__file__)
。script_path_list
请home_dir
注意,这script_path_list
是路径组件的列表,第一个元素是空字符串,因为它最初包含/
此 Linux 路径的根目录路径分隔符:
os.path.abspath(__file__): /home/gabriel/GS/dev/eRCaGuy_dotfiles/useful_scripts/cpu_logger.py
script_path_list: ['', 'home', 'gabriel', 'GS', 'dev', 'eRCaGuy_dotfiles', 'useful_scripts', 'cpu_logger.py']
home_dir: /home/gabriel
我第一次记录这一点的回答是:Python:获取正在运行的脚本所在目录的用户主目录的路径[重复]
进一步:Python 中的相对导入,从一个目录向上
此部分已移至我的新答案:Python 中的相对导入,从一个目录向上。
参见
我对如何在 Bash 中执行同样的事情的回答是: 如何获取正在运行或来源的任何脚本的完整文件路径、完整目录和基本文件名......即使被调用的脚本是从另一个 bash 函数或脚本中调用的,或者正在使用嵌套来源!
这个相关的、有用的答案是:如何在 Python 中获取父目录?
为了使
#!/usr/bin/env python3
顶部的 hash-bang 也能在 Windows 中工作,而不仅仅是在 Linux 中,请参阅我的回答:Python 在 git bash 的命令行中不起作用
解决方案 23:
我使用了 file 的方法,
os.path.abspath(__file__)
但有一个小技巧,它在第一次运行代码时返回 .py 文件,下次运行时会给出 *.pyc 文件的名称,
所以我坚持使用:
inspect.getfile(inspect.currentframe())
或者
sys._getframe().f_code.co_filename
解决方案 24:
我编写了一个考虑 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_))
解决方案 25:
最简单的方法是:
在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>
。
解决方案 26:
以下返回当前主脚本所在的路径。我使用 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]))