如何获得Python中当前执行文件的path?
这可能看起来像一个新手问题,但事实并非如此。 一些常用的方法在所有情况下都不起作用:
sys.argv中[0]
这意味着使用path = os.path.abspath(os.path.dirname(sys.argv[0]))
,但是如果您从另一个目录中的另一个Python脚本运行,则这不起作用,并且这可能会在现实生活中发生。
__文件__
这意味着使用path = os.path.abspath(os.path.dirname(__file__))
,但是我发现这不起作用:
-
py2exe
没有__file__
属性,但有一个解决方法 - 当你使用
execute()
从IDLE运行时,没有__file__
属性 - OS X 10.6我得到的
NameError: global name '__file__' is not defined
有不完整答案的相关问题:
- Python – 查找正在运行的文件的path
- 当前文件的path取决于我如何执行程序
- 如何知道在Python中运行脚本的path?
- 将目录切换到Python脚本的目录
我在寻找一个通用的解决scheme ,一个可以在所有上面的用例中工作的解决scheme 。
更新
这是一个testing用例的结果:
python a.py的输出(在Windows上)
a.py: __file__= a.py a.py: os.getcwd()= C:\zzz b.py: sys.argv[0]= a.py b.py: __file__= a.py b.py: os.getcwd()= C:\zzz
a.py
#! /usr/bin/env python import os, sys print "a.py: sys.argv[0]=", sys.argv[0] print "a.py: __file__=", __file__ print "a.py: os.getcwd()=", os.getcwd() print execfile("subdir/b.py")
子目录/ b.py
#! /usr/bin/env python import os, sys print "b.py: sys.argv[0]=", sys.argv[0] print "b.py: __file__=", __file__ print "b.py: os.getcwd()=", os.getcwd() print
树
C:. | a.py \---subdir b.py
您不能直接确定正在执行的主脚本的位置。 毕竟,有时脚本根本不来自文件。 例如,它可能来自交互式解释器或dynamic生成的只存储在内存中的代码。
但是,您可以可靠地确定模块的位置,因为模块始终是从文件加载的。 如果使用以下代码创build模块并将其放在与主脚本相同的目录中,则主脚本可以导入模块并使用它来定位自己。
SOME_PATH / module_locator.py:
def we_are_frozen(): # All of the modules are built-in to the interpreter, eg, by py2exe return hasattr(sys, "frozen") def module_path(): encoding = sys.getfilesystemencoding() if we_are_frozen(): return os.path.dirname(unicode(sys.executable, encoding)) return os.path.dirname(unicode(__file__, encoding))
SOME_PATH / main.py:
import module_locator my_path = module_locator.module_path()
如果在不同的目录中有几个主脚本,则可能需要module_locator的多个副本。
当然,如果您的主脚本是由其他工具加载的,而这些工具不允许导入与脚本位于同一位置的模块,那么您运气不好。 在这种情况下,您所查询的信息根本不存在于程序中的任何地方。 你最好的select是向工具的作者提交一个bug。
首先,你需要从inspect
和os
导入
from inspect import getsourcefile from os.path import abspath
接下来,无论你想从你find源文件只是使用
abspath(getsourcefile(lambda:0))
我遇到了类似的问题,我认为这可能会解决这个问题:
def module_path(local_function): ''' returns the module path without the use of __file__. Requires a function defined locally in the module. from http://stackoverflow.com/questions/729583/getting-file-path-of-imported-module''' return os.path.abspath(inspect.getsourcefile(local_function))
它适用于普通脚本和闲置。 我所能说的只是为别人尝试
我的典型用法:
from toolbox import module_path def main(): pass # Do stuff global __modpath__ __modpath__ = module_path(main)
现在我使用__modpath__而不是__file__。
简单的答案是, 没有保证的方式来获得你想要的信息 ,但有启发式,几乎总是在实践中。 你可能会看看如何find可执行文件在C中的位置? 。 它从C的angular度讨论了这个问题,但是提出的解决scheme很容易被转换成Python。
您可以使用pathlib
模块中的Path
:
from pathlib import Path # ... Path(__file__)
您可以使用呼叫parent
进一步path:
Path(__file__).parent
查看我的问题的答案从父文件夹导入模块的相关信息,包括为什么我的答案不使用不可靠的__file__
variables。 这个简单的解决scheme应该与不同的操作系统交叉兼容,因为模块os
和inspect
是Python的一部分。
首先,您需要导入部分的inspect和os模块。
from inspect import getsourcefile from os.path import abspath
接下来,在Python代码中需要的地方使用下面的代码行:
abspath(getsourcefile(lambda:0))
怎么运行的:
从内置模块os
(下面的描述)中, abspath
工具被导入。
Mac,NT或Posix的OS例程取决于我们所在的系统。
然后从内置模块导入getsourcefile
(下面的描述)。
从实际的Python对象中获取有用的信息。
-
abspath(path)
返回文件path的绝对/完整版本 -
getsourcefile(lambda:0)
以某种方式获取lambda函数对象的内部源文件,因此在Python shell中返回'<pyshell#nn>'
或返回当前正在执行的Python代码的文件path。
对getsourcefile(lambda:0)
的结果使用abspath
应确保生成的文件path是Python文件的完整文件path。
这个解释的解决scheme最初是基于来自答案的代码如何在Python中获取当前执行文件的path? 。
这应该以跨平台的方式来做(只要你不使用解释器或其他东西):
import os, sys non_symbolic=os.path.realpath(sys.argv[0]) program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))
sys.path[0]
是调用脚本所在的目录(第一个查找该脚本将要使用的模块)。 我们可以从sys.argv[0]
(这是我用os.path.basename
所做的)的末尾取得文件本身的名称。 os.path.join
只是将它们以跨平台的方式粘在一起。 os.path.realpath
只是确保如果我们得到任何与脚本本身不同的名称的符号链接,我们仍然得到脚本的真实名称。
我没有Mac; 所以,我没有在一个testing。 请让我知道它是否有效,因为它似乎应该。 我用Python 3.4在Linux(Xubuntu)中testing了这个。 请注意,这个问题的许多解决scheme不适用于Mac(因为我听说__file__
不存在于Mac上)。
请注意,如果您的脚本是符号链接,它将为您提供链接文件的path(而不是符号链接的path)。
该解决scheme即使在可执行文件中也是健壮的
import inspect, os.path filename = inspect.getframeinfo(inspect.currentframe()).filename path = os.path.dirname(os.path.abspath(filename))