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

Ray*_*ega 462 python scripting file

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

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

  • script_1.py电话script_2.py.
  • 反过来,script_2.py打电话script_3.py.

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

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

小智 548

__file__
Run Code Online (Sandbox Code Playgroud)

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

import os

os.path.realpath(__file__)
Run Code Online (Sandbox Code Playgroud)

  • 但是因为我们只使用这个文件的路径是无关紧要的. (26认同)
  • 人们需要小心这种方法,因为有时候`__file__`会返回'script_name.py',有时会返回'script_name.pyc'.所以输出不稳定. (14认同)
  • @muon没有检查传入的文件名字符串是否存在,并且因为文件路径是相对于cwd的,所以`os.path.realpath`函数假定路径的`dir`部分.`os.path.dirname(os.path.realpath(__ file __))`返回包含该文件的目录.`os.path.dirname(os.path.realpath("__ file __"))`返回cwd.`os.path.dirname(os.path.realpath("here_be_dragons"))`也返回cwd. (7认同)
  • 这很奇怪:当从命令行运行时``__file __'`在引号中(作为字符串)给出了运行cmd的目录,但是`__file__`(没有引号给出了源文件的路径......为什么 (5认同)
  • “名称'__file__'未定义” (2认同)

Pat*_*otz 247

p1.py:

execfile("p2.py")
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • 请注意:此调用不会在不同环境中提供相同的结果.考虑接受Usagi的答案如下:http://stackoverflow.com/a/6628348/851398 (11认同)
  • user13993确实钉了它.应该是`os.path.realpath(__ file __)` (5认同)
  • 用户13993把它钉得更好 (4认同)
  • @faraday:你能提供一个例子吗?我用[inspect.getabsfile()`](http://stackoverflow.com/a/22881871/4279)回答了[类似的问题]它适用于我尝试过的所有情况. (3认同)
  • @Usagi 的答案确实更好吗? (2认同)
  • @osirisgothra:您确实明白 `__file__` 不能与问题中*明确*提到的 `execfile()` 一起使用。 (2认同)
  • 虽然 __file__ 通常足够好,但当你的程序运行在远离 __file__ 的地方时,它就不起作用了。 (2认同)
  • 如果传递了一个模块对象,`inspect.getfile()` 返回`__file__` 属性。`inspect.currentframe()` 返回模块。因此,这是一种昂贵的说法`__file__`。 (2认同)

Bri*_*rns 84

更新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__                               |
Run Code Online (Sandbox Code Playgroud)

对于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
Run Code Online (Sandbox Code Playgroud)

以下是将这些作为函数添加到sys中!感谢@Usagi和@pablog

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

C:\ filepaths\main.py: execfile('foo.py')
C:\ filepaths\foo.py:C execfile('lib/bar.py')
:\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
Run Code Online (Sandbox Code Playgroud)


Usa*_*agi 70

我认为这更清洁:

import inspect
print inspect.stack()[0][1]
Run Code Online (Sandbox Code Playgroud)

并获得相同的信息:

print inspect.getfile(inspect.currentframe())
Run Code Online (Sandbox Code Playgroud)

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

print inspect.stack()[1][1]
Run Code Online (Sandbox Code Playgroud)

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

  • 不建议依赖元组内的位置.目前还不清楚在阅读代码时你想要获得什么数据. (4认同)
  • 如果传递模块对象,`inspect.getfile()`返回`__file__`属性.`inspect.currentframe()`返回模块.因此,这是一种说"__file__"的昂贵方式. (4认同)

小智 40

import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
Run Code Online (Sandbox Code Playgroud)

  • 我刚刚尝试了@Pat Notz 的评论。我认为你可以通过“__file__”获取文件名。 (2认同)

小智 37

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

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

  • 这是拼写`sys.modules ['__ main __'] .__ file__`的一种昂贵的方式,真的. (2认同)

vis*_*khe 13

import os
print os.path.basename(__file__)
Run Code Online (Sandbox Code Playgroud)

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


Dou*_*oug 13

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

from pathlib import Path

current_file: Path = Path(__file__).resolve()
Run Code Online (Sandbox Code Playgroud)

如果要查找当前文件的目录,只需添加.parentPath()语句中即可:

current_path: Path = Path(__file__).parent.resolve()
Run Code Online (Sandbox Code Playgroud)


Bla*_*rad 12

"当前在进程中运行的文件的文件路径"是什么意思并不完全清楚. sys.argv[0]通常包含Python解释器调用的脚本的位置.有关更多详细信息,请查看sys文档.

正如@Tim和@Pat Notz指出的那样,__ file__属性提供了访问权限

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

  • 当我们将 python 程序传递给 win32 exe 时,“print os.path.abspath( __file__ )”和“printspect.getfile(inspect.currentframe() )”不起作用。只有 sys.argv[0] 有效!:) 但你只能得到名字! (2认同)

gar*_*heg 10

我有一个必须在Windows环境下工作的脚本.剪切的代码是我完成的:

import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
Run Code Online (Sandbox Code Playgroud)

这是一个非常糟糕的决定.但它不需要外部库,在我的情况下它是最重要的.

  • 为此,我必须“导入 os,sys”,但到目前为止,它是实际上仅返回字符串末尾没有文件名的路径的最佳答案。 (2认同)

Rea*_*nly 8

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

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


Kwu*_*ite 8

import os
os.path.dirname(os.path.abspath(__file__))
Run Code Online (Sandbox Code Playgroud)

无需检查或任何其他图书馆.

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

  • 怎么会这样?在这种情况下,对我来说工作正常.我得到了文件所在的目录. (2认同)

小智 8

尝试这个,

import os
os.path.dirname(os.path.realpath(__file__))
Run Code Online (Sandbox Code Playgroud)


app*_*eev 6

import sys

print sys.path[0]
Run Code Online (Sandbox Code Playgroud)

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

  • sys.path [0]非常有用,但是给出了script1的路径,而不是脚本3 (2认同)

Pat*_*otz 5

我认为这__file__ 听起来像你也可能想要检查检查模块.


Pab*_*loG 5

您可以使用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'
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

510246 次

最近记录:

6 年,3 月 前