我有调用其他脚本文件的脚本,但我需要获得当前在进程中运行的文件的文件路径。
例如,假设我有三个文件。使用execfile。
script_1.py
调用script_2.py
。script_2.py
调用script_3.py
。我怎样才能从script_3.py
*的代码中获得*script_3.py
的文件名和路径,而不需要把这些信息作为参数从script_2.py
中传递出来?
(执行os.getcwd()
会返回原来的起始脚本的文件路径,而不是当前文件的路径)。
__file__
就像其他人所说的那样,你可以使用 [os.path.realpath]() 来消除符号链接。 你也可以使用 os.path.realpath 来消除符号链接。
import os
os.path.realpath(__file__)
2018-11-28更新:。
下面是Python 2和3的实验总结。 用
main.py - 运行 foo.py foo.py - 运行lib/bar.py。 lib/bar.py - 打印文件路径表达式。
<!--语言。 lang-none -->
| 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
文件。
参见https://stackoverflow.com/questions/27517003/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
为这些被添加到系统中的功能而干杯! 归功于 @Usagi 和 @pablog
基于以下三个文件,并从其文件夹中运行main.python main.py`(也试过用绝对路径的execfiles和从单独的文件夹调用)。
C:\filepaths\main.py。
execfile('foo.py')
。
C:\filepaths\foo.py:
execfile('lib/bar.py')
。
C:\filepaths\libbar.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
如果你的脚本只由一个文件组成,标记为最佳的建议都是正确的。
如果你想从一个可能作为模块导入的文件中找出可执行文件的名称 (即传给当前程序的根文件) 从一个可能作为模块导入的文件中找出可执行文件的名称(即传递给当前程序的 python 解释器的根文件),你需要这样做(让我们假设这是在一个名为 foo.py 的文件中)。
import inspect
print inspect.stack()[-1][1]
。
因为堆栈上的最后一个东西([-1]
)就是进入堆栈的第一个东西(堆栈是LIFO/FILO数据结构)。
那么在文件bar.py中,如果你import foo
,它会打印出bar.py,而不是foo.py,而foo.py是所有这些的值。
__file__
inspect.getfile(inspect.currentframe())
。inspect.stack()[0][1]
。我有一个脚本,必须在windows环境下工作。 这段代码是我完成的。
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/__file__>。
你可以使用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'