模块 __file__ 属性是绝对的还是相对的?

2025-03-05 09:16:00
admin
原创
74
摘要:问题描述:我很难理解__file__。据我了解,__file__返回加载模块的绝对路径。我在生成此代码时遇到了问题:我有一个abc.py带有一条语句的语句print __file__,从/d/projects/ python abc.pyreturns运行。从returnsabc.py运行。有什么原因吗?/d...

问题描述:

我很难理解__file__。据我了解,__file__返回加载模块的绝对路径。

我在生成此代码时遇到了问题:我有一个abc.py带有一条语句的语句print __file__,从/d/projects/ python abc.pyreturns运行。从returnsabc.py运行。有什么原因吗?/d/`projects/abc.py`


解决方案 1:

__file__在 Python 3.9+ 中保证是绝对路径。

在 Python 3.4 中(更新日志)

模块__file__属性(和相关值)现在应该始终默认包含绝对路径,唯一的例外是__main__.__file__直接使用相对路径执行脚本时。

在 Python 3.9 (更新日志)中:

...模块__file__的属性__main__变成了绝对路径


来自文档:

如果模块是从文件加载的,则为加载模块的文件的路径名。__file__某些类型的模块(例如静态链接到解释器的 C 模块)可能缺少此属性。对于从共享库动态加载的扩展模块,它是共享库文件的路径名。

来自@kindall在问题评论中链接的邮件列表主题:

我没有尝试重现这个特定的例子,但原因是我们不想在每次导入时都调用 getpwd(),也不想使用某种进程内变量来缓存当前目录。(getpwd() 相对较慢,有时会直接失败,尝试缓存它有一定的错误风险。)

我们所做的是,在 site.py 中遍历 sys.path 的元素并将它们转换为绝对路径。但是,此代码在 sys.path 前面插入 '' 之前运行,因此 sys.path 的初始值为 ''。

对于其余部分,考虑sys.path不包括''

因此,如果您位于sys.path包含模块的部分之外,您将获得绝对路径。如果您位于sys.path包含模块的部分之内,您将获得相对路径

如果您在当前目录中加载模块,并且当前目录不在sys.path那么您将获得绝对路径。

如果您在当前目录中加载模块,并且当前目录位于,那么sys.path您将获得相对路径。

解决方案 2:

__file__自 Python 3.4 以来是绝对的,除非直接使用相对路径执行脚本:

模块__file__属性(和相关值)现在应始终默认包含绝对路径,唯一的例外是__main__.__file__使用相对路径直接执行脚本时。(由 Brett Cannon 在bpo-18416中贡献。)

但不确定它是否能解析符号链接。

传递相对路径的示例:

$ python script.py

解决方案 3:

后期简单示例:

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:codespy
__file__:cwd_mayhem.py
abspath: C:codespycwd_mayhem.py
cwd:     C:codes
__file__:cwd_mayhem.py
abspath: C:codescwd_mayhem.py

正如@techtonik 所指出的,在 Python 3.4+ 中,这将正常工作,因为__file__它返回一个绝对路径。

解决方案 4:

__file__可以是相对的也可以是绝对的,这取决于所使用的python版本以及是否直接执行模块。

总结:

  • 从 python 3.5 到 3.8__file__如果直接调用模块,则设置为模块相对于当前工作目录的相对路径。否则设置为绝对路径。

  • 从python3.9开始__file__即使直接执行相应模块也设置为绝对路径。

这种行为在 Python 3.9 的新功能中进行了解释(感谢@user0 的评论):

Python 现在获取命令行上指定的脚本文件名的绝对路径(例如python3 script.py:):模块__file__的属性__main__变为绝对路径,而不是相对路径。在当前目录被更改后,这些路径现在仍然有效os.chdir()。作为副作用,__main__在这种情况下,回溯还会显示模块框架的绝对路径。

玩具示例:
例如,具有以下设置(受此答案启发):

# x.py:
from pathlib import Path
import y
print(__file__)
print(Path(__file__))
print(Path(__file__).resolve())
# y.py:
from pathlib import Path
print(__file__)
print(Path(__file__))

x.py位于y.py同一目录中。进入此目录并执行后的不同输出:

python x.py

是:

Python 3.5 – 3.8:

D:py_testsy.py
D:py_testsy.py
x.py
x.py
D:py_testsx.py

Python 3.9 – 3.11

D:py_testsy.py
D:py_testsy.py
D:py_testsx.py
D:py_testsx.py
D:py_testsx.py

解决方案 5:

借助@kindall 提供的 Guido 邮件,我们可以将标准导入过程理解为尝试在 的每个成员中找到模块sys.path,并将文件作为此查找的结果(更多详细信息请参阅PyMOTW 模块和导入)。因此,如果模块位于 中的绝对路径中,则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() 相对较慢,有时甚至会直接失败,

因此您的路径将按原样使用。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3970  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2740  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   79  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   87  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   74  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用