我有调用其他脚本文件的脚本,但我需要获取进程中当前运行的文件的文件路径。
例如,假设我有三个文件。使用Excel文件:
- script_1.py调用script_2.py。
- 反过来,script_2.py调用script_3.py。
如何从script_3.py内的代码中获取script_3.py的文件名和路径,而不必将该信息作为script_2.py的参数传递?
(执行os.getcwd()返回原始启动脚本的文件路径,而不是当前文件的路径。)
正如其他人所说。您还可以使用os.path.realpath来消除符号链接:
1 2 3
| import os
os.path.realpath(__file__) |
P1.PY:
P2.PY:
1 2 3
| 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 |
更新2018-11-28:
下面是对Python2和3的实验的总结。用
main.py-运行foo.pyfoo.py-运行lib/bar.pylib/bar.py-打印文件路径表达式
1 2 3 4 5 6
| | 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().read()),尽管这会影响堆栈帧。只使用import foo和import lib.bar是最简单的,不需要__init__.py文件。
另请参见import和execfile之间的区别
原始答案:
下面是一个基于这个线程中答案的实验-在Windows上使用python 2.7.10。
基于堆栈的是唯一看起来能给出可靠结果的。最后两个语法最短,即-
1 2
| 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:filepathsmain.py:execfile('foo.py')。C:filepathsfoo.py:execfile('lib/bar.py')。C:filepathslibar.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| 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 |
我觉得这比较干净:
1 2
| import inspect
print inspect.stack()[0][1] |
得到的信息与:
1
| print inspect.getfile(inspect.currentframe()) |
其中[0]是堆栈中的当前帧(堆栈顶部),而[1]是文件名,增加以在堆栈中向后移动,即。
1
| print inspect.stack()[1][1] |
将是调用当前帧的脚本的文件名。另外,使用[-1]将使您到达堆栈的底部,即原始调用脚本。
1 2 3 4
| import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only |
如果脚本只包含一个文件,则标记为"最佳"的建议都是正确的。
如果要从一个可能作为模块导入的文件中查找可执行文件(即当前程序传递给python解释器的根文件)的名称,则需要执行此操作(假设该文件位于名为foo.py的文件中):
import inspect
print inspect.stack()[-1][1]
因为栈上的最后一件事([-1]是进入栈中的第一件事(栈是lifo/filo数据结构)。
然后,在file bar.py中,如果您使用cx1(7),它将打印bar.py,而不是foo.py,这将是所有这些的值:
- __file__
- inspect.getfile(inspect.currentframe())
- inspect.stack()[0][1]
1 2
| import os
print os.path.basename(__file__) |
这将只提供文件名。例如,如果文件的abspath为c:abcd abc.py,则第二行将打印abc.py。
不完全清楚您所说的"当前在进程中运行的文件的文件路径"是什么意思。sys.argv[0]通常包含由Python解释器调用的脚本的位置。有关详细信息,请参阅sys文档。
正如@tim和@pat notz指出的,文件属性提供对
the file from which the module was
loaded, if it was loaded from a file
我有一个脚本必须在Windows环境下工作。我已经完成了这段代码的截图:
1 2
| import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0]) |
这是一个愚蠢的决定。但它不需要外部的库,在我的例子中它是最重要的。
__file__属性既适用于包含主执行代码的文件,也适用于导入的模块。
请参阅https://web.archive.org/web/20090918095828/http://pyref.infogami.com//uuuu文件__
1 2
| import os
os.path.dirname(os.path.abspath(__file__)) |
不需要检查或任何其他库。
当我必须导入一个脚本(从另一个目录,然后是执行的脚本)时,这对我很有效,该脚本使用的配置文件与导入的脚本位于同一个文件夹中。
1 2 3
| import sys
print sys.path[0] |
这将打印当前正在执行的脚本的路径
我认为这只是__file__的声音,你可能还想检查模块。
您可以使用inspect.stack()。
1 2 3 4
| import inspect,os
inspect.stack()[0] => (<frame object at 0x00AC2AC0>, 'g:\\Python\\Test\\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()[0]
'], 0)
os.path.abspath (inspect.stack()[0][1]) => 'g:\\Python\\Test\\_GetCurrentProgram.py' |
1 2
| import sys
print sys.argv[0] |
这应该有效:
1 2 3
| import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0])) |
获取执行脚本的目录
1
| print os.path.dirname( inspect.getfile(inspect.currentframe())) |
要保持跨平台(MacOS/Windows/Linux)的迁移一致性,请尝试:
path = r'%s' % os.getcwd().replace('\\','/')
试试这个,
1 2
| import os
os.path.dirname(os.path.realpath(__file__)) |
我编写了一个函数,考虑到Eclipse调试器和UnitTest。它返回您启动的第一个脚本的文件夹。您可以选择指定_uu文件_uuuvar,但主要的是您不必在所有调用层次结构中共享这个变量。
也许你可以处理别人堆积的一些我没看到的特殊案件,但对我来说没关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 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_)) |
我用了带文件的方法__os.path.abspath(__file__)但是有一个小技巧,它返回.py文件当代码第一次运行时,下一次运行给出*.pyc文件的名称所以我留下来:inspect.getfile(inspect.currentframe())或sys._getframe().f_code.co_filename
最简单的方法是:
在Script Pt1.Py中:
1 2
| import subprocess
subprocess.call(['python3',<path_to_script_2.py>]) |
在Script Pt2.Py中:
附言:我试过execfile,但自从它把script_2.py读成字符串后,sys.argv[0]返回。
我一直在使用当前工作目录的操作系统功能,即cwd。这是标准库的一部分,非常容易实现。下面是一个例子:
1 2
| import os
base_directory = os.getcwd() |
大多数答案都是用Python2.x或更早版本编写的。在python 3.x中,print函数的语法已更改为需要括号,即print()。
所以,在python 2.x中,用户13993给出了这个早期的高分答案:
1 2 3
| 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中:
1 2 3
| 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 |
1 2 3 4 5 6 7 8 9 10 11 12
| import os
import wx
# return the full path of this file
print(os.getcwd())
icon = wx.Icon(os.getcwd() + '/img/image.webp', wx.BITMAP_TYPE_PNG, 16, 16)
# put the icon on the frame
self.SetIcon(icon) |
如果只需要不带./或.py的文件名,可以尝试此操作
1 2
| filename = testscript.py
file_name = __file__[2:-3] |
file_name将打印测试脚本您可以通过更改[]内的索引来生成所需的任何内容。