我有调用其他脚本文件的脚本,但是我需要获取该进程中当前正在运行的文件的文件路径。
例如,假设我有三个文件。使用execfile:
script_1.py
来电script_2.py
。- 依次
script_2.py
调用script_3.py
。
我怎样才能获得的文件名和路径script_3.py
,从内部代码script_3.py
,而无需从传递这些信息作为参数script_2.py
?
(执行os.getcwd()
将返回原始启动脚本的文件路径,而不是当前文件的路径。)
我有调用其他脚本文件的脚本,但是我需要获取该进程中当前正在运行的文件的文件路径。
例如,假设我有三个文件。使用execfile:
script_1.py
来电script_2.py
。script_2.py
调用script_3.py
。我怎样才能获得的文件名和路径script_3.py
,从内部代码script_3.py
,而无需从传递这些信息作为参数script_2.py
?
(执行os.getcwd()
将返回原始启动脚本的文件路径,而不是当前文件的路径。)
Answers:
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
inspect.getabsfile()
,它适用于我尝试过的所有情况。
os.path.realpath(__file__)
__file__
返回“ script_name.py”,有时返回“ script_name.pyc”。因此输出不稳定。
"__file__"
中使用引号(作为字符串)运行时,__file__
会给出运行cmd的目录,但是(不带引号则是源文件的路径...这是为什么
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。
更新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
文件。
原始答案:
这是基于该线程答案的实验-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
基于以下三个文件,并从其文件夹运行main.py python 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
我认为这更干净:
import inspect
print inspect.stack()[0][1]
并获得与以下信息相同的信息:
print inspect.getfile(inspect.currentframe())
其中[0]是堆栈中的当前帧(堆栈的顶部),[1]是文件名,请增加以在堆栈中向后移动,即
print inspect.stack()[1][1]
将是调用当前框架的脚本的文件名。另外,使用[-1]将使您到达堆栈的底部,即原始调用脚本。
inspect.getfile()
__file__
如果传递了模块对象,则返回属性。inspect.currentframe()
返回模块。嗯,这是一种昂贵的说法__file__
。
inspect.stack()
是一个非常昂贵的函数,而不仅仅是inspect.currentframe()
,它还调用inspect.getfile()
模块对象。
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
__file__
。
os.path.dirname
将为您提供运行脚本的相对路径。例如,在python ../../test.py
该os.path.dirname
会../../
,而不是绝对路径的脚本。我一直在寻找abspath,但删除了脚本的名称。sys.path的第一个元素显然是答案sys.path[0]
。
如果您的脚本仅包含一个文件,则标记为“最佳”的建议都是正确的。
如果要从可能作为模块导入的文件中找出可执行文件的名称(即,传递给当前程序的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__
确实,这是一种昂贵的拼写方式。
我有一个必须在Windows环境下工作的脚本。这段代码是我完成的:
import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
这是一个不明智的决定。但这不需要外部库,这对我来说是最重要的。
import os
os.path.dirname(os.path.abspath(__file__))
无需检查或任何其他库。
当我必须导入脚本(从与执行脚本所在的目录不同的目录)导入脚本时,此方法对我有用,该脚本使用与导入脚本位于同一文件夹中的配置文件。
该__file__
属性适用于包含主要执行代码的文件以及导入的模块。
参见https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__
我编写了一个函数,该函数考虑了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_))
最简单的方法是:
在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>
。
这是我所使用的,因此我可以将我的代码无处不在。__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__))
这些答案大多数都是用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
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)
__file__
属性是绝对的还是相对的?