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