我无法理解__file__
。据我所知,__file__
返回加载模块的绝对路径。
我遇到问题:我有abc.py
一条语句print __file__
,从/d/projects/
python abc.py
开始运行abc.py
。从/d/
开始运行会返回projects/abc.py
。有什么原因吗?
答案 0 :(得分:90)
__file__
是加载模块的文件的路径名(如果是从文件加载的)。对于静态链接到解释器的C模块,不存在__file__
属性;对于从共享库动态加载的扩展模块,它是共享库文件的路径名。
从@kindall在评论中链接的mailing list thread问题:
我没有尝试重复这个特定的例子,但原因是 我们不希望每次导入都调用getpwd(),也不需要 想要某种进程内变量来缓存当前变量 目录。 (getpwd()相对较慢,有时可能会失败 直接,并试图缓存它有一定的错误风险。)
我们所做的是,site.py中的代码遍历了元素 sys.path并将它们转换为绝对路径。但是这段代码运行了 在''之前插入sys.path的前面,以便初始化 sys.path的值是''。
对于其余部分,请考虑sys.path
不要包含''
。
因此,如果您不在包含该模块的sys.path
部分,那么您将获得绝对路径。如果您位于包含该模块的sys.path
部分内,您将获得相对路径。
如果您在当前目录中加载模块,并且sys.path
中的当前目录不是,您将获得绝对路径。
如果您在当前目录中加载模块,并且sys.path
中的当前目录 ,您将获得相对路径。
答案 1 :(得分:48)
__file__
是绝对since Python 3.4,除非直接使用相对路径执行脚本:
模块
__file__
属性(和相关值)现在应该始终包含绝对路径,当使用相对路径直接执行脚本时,__main__.__file__
唯一例外。 (由Brett Cannon在bpo-18416提供。)
不确定它是否会解析符号链接。
传递相对路径的示例:
$ python script.py
答案 2 :(得分:14)
后期简单示例:
from os import path, getcwd, chdir
def print_my_path():
print('cwd: {}'.format(getcwd()))
print('__file__:{}'.format(__file__))
print('abspath: {}'.format(path.abspath(__file__)))
print_my_path()
chdir('..')
print_my_path()
在Python-2。*下,第二次调用错误地根据当前目录确定path.abspath(__file__)
:
cwd: C:\codes\py
__file__:cwd_mayhem.py
abspath: C:\codes\py\cwd_mayhem.py
cwd: C:\codes
__file__:cwd_mayhem.py
abspath: C:\codes\cwd_mayhem.py
如@techtonik所述,在Python 3.4+中,这将正常工作,因为__file__
返回绝对路径。
答案 3 :(得分:4)
在@kindall提供的Guido邮件的帮助下,我们可以将标准导入过程理解为尝试在sys.path
的每个成员中查找模块,并将文件作为此查找的结果(更多详细信息)在PyMOTW Modules and Imports。)。因此,如果模块位于sys.path
中的绝对路径中,则结果是绝对的,但如果它位于sys.path
中的相对路径中,则结果是相对的。
现在site.py
启动文件只负责提供sys.path
中的绝对路径,但初始''
除外,所以如果不通过其他方式更改它,而不是设置PYTHONPATH (在sys.path
前缀之前,它的路径也是绝对的),你将始终获得绝对路径,但是当通过当前目录访问模块时。
现在,如果你以一种有趣的方式欺骗sys.path,你就可以得到任何东西。
例如,如果foo.py
中的示例模块/tmp/
包含以下代码:
import sys
print(sys.path)
print (__file__)
如果你进入/ tmp,你会得到:
>>> import foo
['', '/tmp', '/usr/lib/python3.3', ...]
./foo.py
进入/home/user
时,如果您添加/tmp
PYTHONPATH
,则会获得:
>>> import foo
['', '/tmp', '/usr/lib/python3.3', ...]
/tmp/foo.py
即使添加../../tmp
,它也会被标准化,结果也是一样。
但是如果不是使用PYTHONPATH
而是直接使用一些有趣的路径
你得到的结果和事业一样有趣。
>>> import sys
>>> sys.path.append('../../tmp')
>>> import foo
['', '/usr/lib/python3.3', .... , '../../tmp']
../../tmp/foo.py
Guido在上面引用的帖子中解释了为什么python不会尝试转换绝对路径中的所有条目:
我们不想在每次导入时调用getpwd().... getpwd()相对较慢,有时可能会彻底失败,
因此,您的路径 。