如何获取当前正在执行的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获取文件名和路径,而不必将该信息作...

问题描述:

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

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

  • script_1.py呼叫script_2.py

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

如何从内部代码中script_3.py获取文件名和路径,而不必将该信息作为参数传递?script_3.pyscript_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 fooimport 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:

我想做得更好,因为我需要更多信息。获取方法如下:

  1. 正在运行的脚本的完整路径

  2. 脚本目录

  3. 脚本的基本文件名

  4. 不带扩展名的文件名

  5. 脚本的扩展

  6. 运行脚本的用户的主目录

  7. 脚本所在用户的主目录

来自我的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_listhome_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 中的相对导入,从一个目录向上。

参见

  1. 我对如何在 Bash 中执行同样的事情的回答是: 如何获取正在运行来源的任何脚本的完整文件路径完整目录基本文件名......即使被调用的脚本是从另一个 bash 函数或脚本中调用的,或者正在使用嵌套来源!

  2. 这个相关的、有用的答案是:如何在 Python 中获取父目录?

  3. 为了使#!/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]))
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用