例如,假设我有三个文件。使用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 楼
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
评论
注意:在不同的环境下,此调用不会产生相同的结果。考虑接受以下Usagi的答案:stackoverflow.com/a/6628348/851398
–法拉第
2014年5月5日7:41
@faraday:您能举个例子吗?我已经使用inspect.getabsfile()回答了类似的问题,它适用于我尝试过的所有情况。
– jfs
2014年4月5日在17:04
不,user13993钉得更好
– osirisgothra
15年8月13日在4:49
user13993确实钉住了它。应该是os.path.realpath(__ file__)
–uchuugaka
15年8月13日在9:02
inspect.getfile()如果传递了模块对象,则返回__file__属性。 inspect.currentframe()返回模块。因此,这是__file__的昂贵表达方式。
–马丁·彼得斯(Martijn Pieters)♦
18年5月12日在19:01
#2 楼
__file__
如其他人所说。您可能还希望使用os.path.realpath消除符号链接:
import os
os.path.realpath(__file__)
评论
需要注意这种方法,因为有时__file__返回'script_name.py',有时返回'script_name.pyc'。因此输出不稳定。
–机械师
2015年9月5日在23:53
但是,由于我们仅使用此文件的路径,因此不相关。
– Uwe Koloska
16-9-29在9:36
这很奇怪:从命令行“ __file__”中用引号(作为字符串)运行时,给出运行cmd的目录,但是__file __(不带引号则给出了源文件的路径...为什么?
–μon
18年5月9日在13:53
@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。
–杰米·布尔(Jamie Bull)
18-10-26在8:11
#3 楼
更新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
文件。另请参阅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
这是将它们作为函数添加到sys的功能!归功于@Usagi和@pablog
基于以下三个文件,并使用
python main.py
在其文件夹中运行main.py(也尝试了具有绝对路径并从单独文件夹中调用的execfile)。 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:\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
#4 楼
我认为这更干净:import inspect
print inspect.stack()[0][1]
并获得与以下信息相同的信息:
print inspect.getfile(inspect.currentframe())
其中[0 ]是堆栈中的当前帧(堆栈顶部),[1]是文件名,在堆栈中向后递增,即
print inspect.stack()[1][1]
调用当前框架的脚本的文件名。另外,使用[-1]将使您到达堆栈的底部,即原始调用脚本。
评论
不建议依靠元组内部的位置。根本不清楚您在读取代码时要获取的数据。
– jpmc26
18年1月19日,2:13
inspect.getfile()如果传递了模块对象,则返回__file__属性。 inspect.currentframe()返回模块。因此,这是__file__的昂贵表达方式。
–马丁·彼得斯(Martijn Pieters)♦
18年5月12日在19:01
inspect.stack()是一个非常昂贵的函数,而不仅仅是inspect.currentframe(),它也对模块对象调用inspect.getfile()。
–马丁·彼得斯(Martijn Pieters)♦
18年5月12日在19:03
#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
评论
我刚刚尝试了@Pat Notz的评论。我认为您可以通过__file__获取文件名。
– hlin117
2015年4月25日在17:51
在Python3中,os.path.dirname将为您提供运行脚本的相对路径。例如在python ../../test.py中,os.path.dirname将是../../,而不是脚本的绝对路径。我一直在寻找abspath,但删除了脚本的名称。 sys.path的第一个元素显然是答案sys.path [0]。
–aerijman
19年11月13日在14:42
#6 楼
如果您的脚本仅包含一个文件,则标记为“最佳”的建议都是正确的。如果要从可能作为模块导入的文件中找出可执行文件的名称(即,传递给当前程序的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]
评论
它运行良好,但不适用于Eclipse的单元测试,我得到了/home/user/Softwares/eclipse/plugins/org.python.pydev_4.5.5.201603221110/pysrc
– hayj
16年6月14日在14:29
实际上,这是一种昂贵的拼写sys.modules ['__ main __'] .__ file__的方式。
–马丁·彼得斯(Martijn Pieters)♦
18年5月12日在19:08
#7 楼
import os
print os.path.basename(__file__)
这只会给我们文件名。即如果文件的绝对路径为c:\ abcd \ abc.py,则第二行将打印abc.py
#8 楼
尚不清楚“进程中当前正在运行的文件的文件路径”是什么意思。sys.argv[0]
通常包含由Python解释器调用的脚本的位置。检查系统文档以获取更多详细信息。
@Tim和@Pat Notz指出,__file__属性提供对
模块来源文件的访问权限
已加载(如果已从文件加载)
评论
当我们将python程序传递给win32 exe时,“ print os.path.abspath(file)”和“ print inspect.getfile(inspect.currentframe())”不起作用。仅sys.argv [0]有效! :)但您只会得到名字!
– aF。
2011-09-1 15:02
#9 楼
我有一个必须在Windows环境下工作的脚本。这段代码是我完成的:
import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
这是一个很棘手的决定。但这不需要外部库,这对我来说是最重要的。
评论
为此,我必须“导入os,sys”,但到目前为止,这是最好的答案,它实际上仅返回字符串末尾没有文件名的路径。
– Emmagras
2014-10-18 15:40
#10 楼
试试这个,import os
os.path.dirname(os.path.realpath(__file__))
#11 楼
import os
os.path.dirname(os.path.abspath(__file__))
不需要检查或任何其他库。
当我不得不导入一个脚本(从不同于执行脚本的其他目录)导入时,此方法对我有用与导入脚本位于同一文件夹中的配置文件。
评论
如果当前工作目录(os.getcwd)与文件所在的目录不同,则将无法产生所需的答案。
–铁枕
2014年8月1日在20:59
为何如此?在这种情况下对我来说很好。我得到文件所在的目录。
– Michael Mior
2014年8月13日在1:39
@IronPillow也许这个答案将帮助您满足您的需求。 stackoverflow.com/a/41546830/3123191
– Kwuite
17年2月23日在15:21
#12 楼
__file__
属性适用于包含主要执行代码的文件以及导入的模块。请参阅https://web.archive.org/web/20090918095828/http://pyref.infogami。 com / __ file__
#13 楼
import sys
print sys.path[0]
这将打印当前正在执行的脚本的路径
评论
sys.path [0]非常有用,但是提供了script1的路径,而不是请求的script3的路径
–詹姆斯
2011年1月28日,下午1:26
至少在OS X(2.7版)上,我认为这没有可靠的作用。如果直接执行相同的文件,它将起作用。从repl无效,尤其是从导入的鸡蛋中
–uchuugaka
15年8月13日在8:58
#14 楼
由于Python 3相当主流,因此我想提供一个pathlib
答案,因为我认为它现在可能是访问文件和路径信息的更好工具。from pathlib import Path
current_file: Path = Path(__file__).resolve()
如果要查找当前文件的目录,只需在
.parent
语句中添加Path()
即可:current_path: Path = Path(__file__).parent.resolve()
#15 楼
我认为这只是__file__
听起来您可能还想检出检查模块。评论
啊... execfile很棘手。请参阅我的其他有关使用inspect模块的文章。
– Pat Notz
08年9月8日在23:03
#16 楼
您可以使用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'
#17 楼
import sys
print sys.argv[0]
评论
不幸的是,这仅在以完整路径调用脚本时才有效,因为它仅在命令行上返回“第一个参数”,即对脚本的调用。
– Cregox
2010年5月13日17:40
#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)
评论
不鼓励仅使用代码的答案。请添加一些有关如何解决问题或与现有答案有何不同的解释。来自评论
–尼克
19年5月5日,下午1:51
#20 楼
获取执行脚本的目录 print os.path.dirname( inspect.getfile(inspect.currentframe()))
#21 楼
我一直只使用“当前工作目录”或CWD的os功能。这是标准库的一部分,非常易于实现。这里是一个示例:
import os
base_directory = os.getcwd()
评论
您可以修改答案,使其适用于提出的问题吗?此答案不适用于“如何获取当前正在执行的文件的路径和名称?”的问题。
–马可
19年3月14日在16:17
这给出了运行python命令的路径。因此,当您在已经存在的同一文件夹中运行python script.py命令时,它似乎可以工作,而实际上与在Linux上运行pwd相同。
–乔治
19年7月14日在13:10
#22 楼
这是我使用的东西,因此我可以将我的代码无处不在。始终定义__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__))
#23 楼
我在__file__os.path.abspath(__file__)
中使用了此方法,但是有一个小技巧,它会在第一次运行代码时返回.py文件。
下一次运行给出* .pyc的名称文件
,所以我留在:
inspect.getfile(inspect.currentframe())
或
sys._getframe().f_code.co_filename
#24 楼
我编写了一个函数,该函数考虑了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_))
#25 楼
要保持跨平台(macOS / Windows / Linux)的迁移一致性,请尝试:path = r'%s' % os.getcwd().replace('\','/')
评论
错了这将为您提供当前路径,而不是当前文件的路径。
–查尔斯·普拉格
18-10-10在13:09
#26 楼
最简单的方法是:在script_1.py中的:
在script_2.py中的
import subprocess
subprocess.call(['python3',<path_to_script_2.py>])
在脚本_2.py中:
sys.argv[0]
PS:我尝试过
execfile
,但是由于它以字符串形式读取script_2.py,因此sys.argv[0]
返回了<string>
。#27 楼
这些答案大多数是用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
#28 楼
如果只希望文件名不包含./
或.py
,则可以尝试以下操作filename = testscript.py
file_name = __file__[2:-3]
file_name
将打印测试脚本,您可以通过更改内部索引来生成所需的任何内容[]
#29 楼
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)
评论
os.getcwd()返回过程的当前工作目录,而不是当前正在执行的文件的目录。这似乎可以返回正确的结果,但是在很多情况下,结果将不是当前文件的父目录。如上面建议的,使用os.path.dirname(file)更好。
–samaspin
15年5月22日在14:17
评论
相关:Python __file__属性是绝对属性还是相对属性?os.path.realpath(文件)
相关:如何正确确定当前脚本目录?