【问题标题】:How to make an "always relative to current module" file path?如何制作“始终相对于当前模块”的文件路径?
【发布时间】:2012-04-16 12:37:11
【问题描述】:

假设您有一个包含以下内容的模块

myfile = open('test.txt', 'r')

“test.txt”文件在同一个文件夹中。如果您将运行该模块,则该文件将成功打开。

现在,假设您从另一个文件夹中的另一个模块导入该模块。不会在与该代码所在的模块相同的文件夹中搜索该文件。

那么如何让模块在同一个文件夹中优先搜索具有相对路径的文件呢?

使用“__file__”或“os.getcwd()”有多种解决方案,但我希望有一种更简洁的方法,例如传递给 open() 或 file() 的字符串中的相同特殊字符。

【问题讨论】:

  • os.getcwd() 有什么问题?
  • os.getcwd() 返回第一个模块的路径,该模块导入了该模块,或者导入了另一个导入它的模块。第一个模块可能在许多目录中。所以输入os.getcwd()+'something/somethingelse/yetanother/finallyhere' 看起来不是很优雅

标签: python module relative-path


【解决方案1】:

解决方案是使用__file__,它很干净:

import os

TEST_FILENAME = os.path.join(os.path.dirname(__file__), 'test.txt')

【讨论】:

  • import os.path 毫无意义,当您执行import os 时,模块会为您导入os.pathos 是特殊的方式)。可以使用from os import path,但在os 模块的情况下并不常见。很可能他的模块中已经有import os,或者很快就会需要一个。因此,import os 几乎总是最佳选择。
  • 我想这是尽可能干净的。更多的东西会要求改变官方 Python 解释器的工作方式。
  • os 已经导入 os.path 的事实是一个实现细节。虽然现在已经建立了约定并且不太可能改变,但您不应该依赖实现细节。使用os.path 时,显式导入os.path 绝不是毫无意义的。
  • 请先添加os.path.realpath() 以获取绝对路径。
【解决方案2】:

对于从.py 文件加载的普通模块,__file__ 应该存在并且可用。要将来自 __file__ 的信息加入到您的相对路径中,自 2014 年以来提供了比 os.path 接口更新的选项:

from pathlib import Path

here = Path(__file__).parent
fname = here / "test.txt"
with fname.open() as f:
    ...

pathlib 在 3.4 中添加到 Python - 请参阅 PEP428。对于仍使用 Python 2.7 并希望使用相同 API 的用户,backport is available

请注意,当您使用 Python 包时,有更好的方法可用于阅读资源 - 您可以考虑移至 importlib-resources。这需要 Python 3.7+,对于旧版本,您可以使用 pkgutil。正确打包资源而不是加入相对于源树的数据文件的一个优点是,代码在未提取到文件系统(例如 zip 文件中的包)的情况下仍然可以工作。有关在包中读取/写入数据文件的更多详细信息,请参阅How to read a (static) file from inside a Python package?

【讨论】:

  • Path(来自 pathlib)提供了许多方便的跨平台功能,与 os 相比,这将是总体上最简洁的方法。
  • 因为它使用的是 pathlib,所以这是我的首选解决方案。
猜你喜欢
  • 2022-12-13
  • 1970-01-01
  • 2017-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
相关资源
最近更新 更多