我有调用其他脚本文件的脚本,但我需要获取当前在该进程中运行的文件的文件路径。
例如,假设我有三个文件。使用execfile:
script_1.py
来电script_2.py
。 script_2.py
会调用script_3.py
。 如何从script_3.py
中的代码中获取 script_3.py
,的文件名和路径,而不必将该信息作为参数传递来自script_2.py
?
(执行os.getcwd()
返回原始起始脚本的文件路径,而不是当前文件。)
答案 0 :(得分:530)
答案 1 :(得分:237)
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
答案 2 :(得分:78)
更新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
这些是作为函数添加到 sys 的!归功于@Usagi和@pablog
基于以下三个文件,并使用python main.py
从其文件夹运行main.py(也尝试使用绝对路径的execfiles并从单独的文件夹调用)。
C:\ filepaths \ main.py: execfile('foo.py')
C:\ filepaths \ foo.py: execfile('lib/bar.py')
C:\文件路径\ 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
答案 3 :(得分:68)
我认为这更清洁:
import inspect
print inspect.stack()[0][1]
并获取与以下相同的信息:
print inspect.getfile(inspect.currentframe())
其中[0]是堆栈中的当前帧(堆栈顶部),[1]是文件名,增加到堆栈中的后退,即
print inspect.stack()[1][1]
将是调用当前帧的脚本的文件名。此外,使用[-1]将使您到达堆栈的底部,即原始调用脚本。
答案 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
答案 5 :(得分:36)
如果您的脚本只包含一个文件,那么标记为最佳的建议都是正确的。
如果要从可作为模块导入的文件中找出可执行文件的名称(即传递给当前程序的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]
答案 6 :(得分:13)
import os
print os.path.basename(__file__)
这将只给我们文件名。即如果文件的abspath是c:\ abcd \ abc.py那么第二行将打印abc.py
答案 7 :(得分:12)
“进程中当前运行的文件的文件路径”是什么意思并不完全清楚。
sys.argv[0]
通常包含Python解释器调用的脚本的位置。
查看sys documentation了解详情。
正如@Tim和@Pat Notz指出的那样,__ file__属性提供了对
的访问模块所在的文件 如果已从文件加载
,则加载
答案 8 :(得分:10)
我有一个必须在Windows环境下工作的脚本。 我已经完成了这段代码:
import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
这是一个非常糟糕的决定。但它不需要外部库,在我的情况下它是最重要的。
答案 9 :(得分:8)
__file__
属性适用于包含主执行代码的文件以及导入的模块。
请参阅https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__
答案 10 :(得分:8)
import os
os.path.dirname(os.path.abspath(__file__))
无需检查或任何其他图书馆。
当我必须导入脚本(从不同的目录然后执行的脚本)时,这对我有用,它使用与导入的脚本位于同一文件夹中的配置文件。
答案 11 :(得分:5)
我认为这只是__file__
听起来您可能还想查看inspect module。
答案 12 :(得分:5)
import sys
print sys.path[0]
这将打印当前正在执行的脚本的路径
答案 13 :(得分:4)
您可以使用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'
答案 14 :(得分:4)
尝试一下
import os
os.path.dirname(os.path.realpath(__file__))
答案 15 :(得分:3)
import sys
print sys.argv[0]
答案 16 :(得分:2)
这应该有效:
import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
答案 17 :(得分:1)
获取执行脚本的目录
print os.path.dirname( inspect.getfile(inspect.currentframe()))
答案 18 :(得分:1)
由于Python 3相当主流,因此我想提供一个pathlib
答案,因为我认为它现在可能是访问文件和路径信息的更好工具。
from pathlib import Path
current_file: Path = Path(__file__).resolve()
如果要查找当前文件的目录,就像将.parent
添加到Path()
语句一样简单:
current_path: Path = Path(__file__).parent.resolve()
答案 19 :(得分:1)
print(__file__)
print(__import__("pathlib").Path(__file__).parent)
答案 20 :(得分:1)
要保持跨平台(macOS / Windows / Linux)的迁移一致性,请尝试:
path = r'%s' % os.getcwd().replace('\\','/')
答案 21 :(得分:0)
最简单的方法是:
script_1.py: 中的
import subprocess
subprocess.call(['python3',<path_to_script_2.py>])
script_2.py: 中的
sys.argv[0]
P.S。:我已尝试execfile
,但由于它将script_2.py作为字符串读取,sys.argv[0]
返回<string>
。
答案 22 :(得分:0)
我写了一个函数,它考虑了eclipse 调试器和 unittest 。 它返回您启动的第一个脚本的文件夹。您可以选择指定 __ file __ var,但主要的是您不必在所有调用层次结构中共享此变量。
也许你可以处理其他人堆叠我没看到的特殊情况,但对我来说没关系。
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_))
答案 23 :(得分:0)
我用__file__的方法
os.path.abspath(__file__)
但有一个小技巧,它返回.py文件
当代码第一次运行时,
下一次运行给出* .pyc文件的名称
所以我留下来:
inspect.getfile(inspect.currentframe())
或
sys._getframe().f_code.co_filename
答案 24 :(得分:0)
这是我所使用的,因此我可以将我的代码无处不在。始终定义__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__))
答案 25 :(得分:-1)
我一直只是使用“当前工作目录”或CWD的os功能。这是标准库的一部分,非常容易实现。 这是一个示例:
import os
base_directory = os.getcwd()
答案 26 :(得分:-2)
大多数答案都是使用Python 2.x或更早版本编写的。在Python 3.x中,print函数的语法已更改为需要括号,即print()。
因此,在Python 2.x中来自user13993的这个较早的高分答案:
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
在Python 3.x中出现:
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
答案 27 :(得分:-3)
如果你只想要没有./
或.py
的文件名,你可以试试这个
filename = testscript.py
file_name = __file__[2:-3]
file_name
将打印测试脚本
您可以通过更改[]
答案 28 :(得分:-3)
import os
import wx
# return the full path of this file
print(os.getcwd())
icon = wx.Icon(os.getcwd() + '/img/image.png', wx.BITMAP_TYPE_PNG, 16, 16)
# put the icon on the frame
self.SetIcon(icon)