这似乎是一个新手问题,但事实并非如此 . 一些常见的方法并不适用于所有情况:
sys.argv [0]
这意味着使用 path = os.path.abspath(os.path.dirname(sys.argv[0]))
,但如果您从另一个目录中的另一个Python脚本运行,则这不起作用,这可能发生在现实生活中 .
file
这意味着使用 path = os.path.abspath(os.path.dirname(__file__))
,但我发现这不起作用:
-
py2exe
没有__file__
属性,但有一个workaround -
当您使用
execute()
从IDLE运行时,没有__file__
属性 -
OS X 10.6我得到
NameError: global name '__file__' is not defined
回答不完整的相关问题:
我正在寻找一个适用于所有上述用例的 generic solution .
更新
这是测试用例的结果:
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")
subdir / 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
11 回答
您无法直接确定正在执行的主脚本的位置 . 毕竟,有时脚本根本不是来自文件 . 例如,它可以来自交互式解释器或仅存储在存储器中的动态生成的代码 .
但是,您可以可靠地确定模块的位置,因为模块始终从文件加载 . 如果使用以下代码创建模块并将其放在与主脚本相同的目录中,则主脚本可以导入模块并使用它来定位自身 .
SOME_PATH / module_locator.py:
SOME_PATH / main.py:
如果在不同目录中有多个主脚本,则可能需要多个module_locator副本 .
当然,如果您的主脚本是由某些其他工具加载的,这些工具不允许您导入与您的脚本位于同一位置的模块,那么您就不走运了 . 在这种情况下,您所追求的信息根本不存在于您的程序中的任何位置 . 您最好的选择是向该工具的作者提交错误 .
首先,您需要从
inspect
和os
导入接下来,无论您想从哪里找到源文件,只需使用即可
我遇到了类似的问题,我认为这可能会解决问题:
它适用于常规脚本和空闲 . 我只能说是为别人试试吧!
我的典型用法:
现在我使用__modpath__而不是__file__ .
简短的回答是 there is no guaranteed way to get the information you want ,但是有一些启发式方法几乎总是在实践中起作用 . 你可能会看How do I find the location of the executable in C? . 它从C的角度讨论了这个问题,但是提出的解决方案很容易转换成Python .
这个解决方案即使在可执行文件中也很强
有关相关信息,请参阅我对问题Importing modules from parent folder的回答,包括为什么我的答案不使用不可靠的
__file__
变量 . 这个简单的解决方案应该与不同的操作系统交叉兼容,因为模块os
和inspect
是Python的一部分 .首先,您需要导入 inspect 和 os 模块的部分内容 .
接下来,在Python代码中的任何其他位置使用以下行:
工作原理:
从内置模块
os
(下面的说明)中,导入abspath
工具 .然后从内置模块
inspect
导入getsourcefile
(以下描述) .abspath(path)
返回文件路径的绝对/完整版本getsourcefile(lambda:0)
以某种方式获取lambda函数对象的内部源文件,因此在Python shell中返回'<pyshell#nn>'
或返回当前正在执行的Python代码的文件路径 .在
getsourcefile(lambda:0)
的结果上使用abspath
应确保生成的文件路径是Python文件的完整文件路径 .这个解释的解决方案最初是基于How do I get the path of the current executed file in Python?答案的代码 .
这应该以跨平台的方式完成(只要你没有使用解释器或其他东西):
sys.path[0]
是您的调用脚本所在的目录(它首先查找该脚本要使用的模块) . 我们可以在sys.argv[0]
结尾处取文件本身的名称(这是我用os.path.basename
做的) .os.path.join
只是坚持他们以跨平台的方式在一起 .os.path.realpath
只是确保我们得到的任何符号链接的名称不同于脚本本身,我们仍然可以得到脚本的真实名称 .我没有在一个上测试过这个 . 请告诉我它是否有效,看起来应该如此 . 我使用Python 3.4在Linux(Xubuntu)中测试了这个 . 请注意,针对此问题的许多解决方案都没有听说过Mac上没有
__file__
.请注意,如果您的脚本是符号链接,它将为您提供链接到的文件的路径(而不是符号链接的路径) .
您可以使用
pathlib
模块中的Path
:您可以使用
parent
调用进一步的路径:你简单地叫了:
代替:
abspath()
为您提供sys.argv[0]
的绝对路径(您的代码所在的文件名),dirname()
返回没有文件名的目录路径 .只需添加以下内容:
要么:
如果代码来自文件,您可以获取其全名
您还可以将函数名称检索为
f_code.co_name