例如,假设我有三个文件。使用execfile:
- `script_1.py` 调用 `script_2.py`。 - `script_2.py` 又调用 `script_3.py`。
在不必从 `script_2.py` 传递该信息作为参数的情况下,我如何从 `script_3.py` 的代码中获取
script_3.py
的文件名和路径?(执行 `os.getcwd()` 返回的是原始启动脚本的文件路径,而不是当前文件的路径。)
script_3.py
的文件名和路径?__file__
会返回'script_name.py',而其他时候会返回'script_name.pyc',所以输出不稳定。 - mechatroner"__file__"
时,它会给出cmd所在的目录,但是不加引号的__file__
会给出源文件的路径……为什么会这样? - muonos.path.realpath
函数假设路径中的“dir”部分是当前工作目录。 os.path.dirname(os.path.realpath(__file__))
返回包含该文件的目录。
os.path.dirname(os.path.realpath("__file__"))
返回当前工作目录。
os.path.dirname(os.path.realpath("here_be_dragons"))
同样返回当前工作目录。 - Jamie BullFULL_PATH_TO_SCRIPT
、SCRIPT_DIRECTORY
、FILENAME
、FILENAME_NO_EXTENSION
、FILENAME_EXTENSION
、HOME_DIR_USER
和HOME_DIR_SCRIPT
。 - undefinedp1.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.getabsfile()
回答了类似的问题,并且对我尝试过的所有情况都起作用。 - jfsos.path.realpath(__file__)
。 - uchuugakainspect.getfile()
函数会返回 __file__
属性。而 inspect.currentframe()
函数则返回该模块。因此,这种方式是昂贵的,相当于说出了 __file__
。 - Martijn Pieters更新 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.bar
- 不需要 __init__.py
文件。
另请参阅 Difference between import and 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
python main.py
运行 main.py(也尝试了使用绝对路径执行文件和从其他文件夹调用)。execfile('foo.py')
execfile('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
我认为这更简洁:
import inspect
print inspect.stack()[0][1]
并且获得与以下信息相同的内容:
print inspect.getfile(inspect.currentframe())
[0]是当前堆栈帧(顶部),[1]是文件名,增加可向后跳转堆栈。
print inspect.stack()[1][1]
使用__file__来获取调用当前帧的脚本文件名。同时,使用[-1]可以让你到达堆栈底部,即原始调用脚本。
inspect.getfile()
会返回__file__
属性。而inspect.currentframe()
则会返回该模块。因此,这种方式实际上是一个昂贵的方法来获取__file__
。 - Martijn Pietersinspect.stack()
是一个相当昂贵的函数,比仅使用 inspect.currentframe()
更昂贵,并且它也会在模块对象上调用 inspect.getfile()
。 - Martijn Pietersimport os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
__file__
获取文件名。 - hlin117os.path.dirname
会给你相对路径,从你运行脚本的位置开始计算。例如,在python ../../test.py
中,os.path.dirname
将是../../
而不是脚本的绝对路径。我一直在寻找abspath
但是需要去掉脚本的名称。显然,sys.path[0]
的第一个元素就是答案。 - aerijman如果您的脚本只包含一个文件,则标记为最佳的建议都是正确的。
如果您想从可能作为模块导入的文件中找出可执行文件的名称(即传递给当前程序的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__
的意思。 - Martijn Pieters由于Python 3已经非常流行,我想包括一个pathlib
的答案,因为我认为它现在可能是访问文件和路径信息的更好工具。
from pathlib import Path
current_file: Path = Path(__file__).resolve()
如果您正在寻找当前文件的目录,只需在 Path()
语句中添加 .parent
即可:current_path: Path = Path(__file__).parent.resolve()
“the filepath of the file that is currently running within the process”这句话的意思不是很清楚。sys.argv[0]
通常包含由Python解释器调用的脚本的位置。
请查看sys文档以获取更多详细信息。
正如@Tim和@Pat Notz所指出的,__file__属性提供了访问以下内容的途径:
如果模块是从文件加载的,则为该模块所加载的文件
import os
print os.path.basename(__file__)
这将只会给我们文件名。例如,如果文件的绝对路径是c:\abcd\abc.py,则第二行将打印出abc.py
我有一个必须在Windows环境下工作的脚本。 以下是我已经完成的代码片段:
import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
这是相当"hacky"的决定。但它不需要外部库,而且在我的情况下是最重要的事情。
__file__
属性是绝对路径还是相对路径? - kenorb