当 CWD 发生变化时,如何在 Python 模块中使用相对路径?

Posted

技术标签:

【中文标题】当 CWD 发生变化时,如何在 Python 模块中使用相对路径?【英文标题】:How do I use a relative path in a Python module when the CWD has changed? 【发布时间】:2011-05-10 09:27:18 【问题描述】:

我有一个 Python 模块,它使用模块目录的子目录中的一些资源。在搜索堆栈溢出并找到相关答案后,我设法使用类似

的方法将模块定向到资源
import os
os.path.join(os.path.dirname(__file__), 'fonts/myfont.ttf')

当我从其他地方调用模块时这工作正常,但是当我在更改当前工作目录后调用模块时它会中断。问题是__file__的内容是相对路径,没有考虑到我改了目录:

>>> mymodule.__file__
'mymodule/__init__.pyc'
>>> os.chdir('..')
>>> mymodule.__file__
'mymodule/__init__.pyc'

如何在__file__ 中编码绝对路径,或者除此之外,无论当前工作目录是什么,我如何访问模块中的资源?谢谢!

【问题讨论】:

【参考方案1】:

在lunaryorn's answer 的基础上,我在模块顶部保留了一个函数,我必须在其中构建多个路径。这样可以避免我重复输入joins。

def package_path(*paths, package_directory=os.path.dirname(os.path.abspath(__file__))):
    return os.path.join(package_directory, *paths)

要构建路径,可以这样调用它:

font_file = package_path('fonts', 'myfont.ttf')

或者如果你只需要包目录:

package_directory = package_path()

【讨论】:

这是不好的做法,并且可能会在许多不同的情况下中断。请改用pkgutil.get_data()【参考方案2】:

将模块目录的绝对路径存储在模块的最开始:

package_directory = os.path.dirname(os.path.abspath(__file__))

之后,根据这个package_directory加载你的资源:

font_file = os.path.join(package_directory, 'fonts', 'myfont.ttf')

毕竟,不要修改进程范围的资源,如当前工作目录。在编写良好的程序中,从来没有真正需要更改工作目录,因此请避免使用os.chdir()

【讨论】:

谢谢,完美!我也会记住您的评论以避免更改工作目录。 我知道这是一个老问题,但不知何故又出现了。 -- 这是不好的做法,可能会在许多不同的情况下中断。请改用pkgutil.get_data() @sinoroc 您能否详细说明您认为这种不良做法的原因并举例说明何时可能会中断? @pfabri 有时东西是直接从 zip 存档导入的,所以 __file__ 不会有有意义/可用的值。有一些关于它的信息,我没有一个具体的参考可以给你。但也许读过这个问题:***.com/questions/6028000/…

以上是关于当 CWD 发生变化时,如何在 Python 模块中使用相对路径?的主要内容,如果未能解决你的问题,请参考以下文章

当 UINavigation 的 Translucent 设置为 false 时,视图约束发生变化

当 UITextView 大小发生变化时,如何调整 UITableViewCell 的大小?

当逻辑语句的结果发生变化时如何执行回调?

当 Extjs 中的窗口大小发生变化时如何显示“分页工具栏”?

当 Kotlin 中的数据发生变化时,如何在 RecyclerView 中重新绑定项目?

当SwiftUI中的相关实体发生变化时,如何更新@FetchRequest?