Python 读取资源文件的正确方式:从相对路径陷阱到 importlib.resources

咖啡半糖
咖啡半糖
发布时间:2026-10-14 | 3人浏览过
原创

本文详解 Python 中读取资源文件的常见误区与最佳实践。直接运行脚本时相对路径有效,但在包(package)内部调用时易因工作目录不同导致 FileNotFoundError。文章对比了基于 os.path 的笨拙解法与 Python 3.7+ 推荐的 importlib.resources 模块,并深入解析如何处理嵌套子目录中的资源文件,确保打包部署时资源文件能被正确识别。

直接运行脚本时的文件读取

在 Python 开发中,若资源文件与当前执行的 .py 脚本位于同一目录,通常可直接通过文件名进行读取。例如:


with open('test.txt') as f: 
  content = f.read() 
print('文件中的内容为:', content) 

运行效果如下图所示:

包内调用时的路径陷阱

然而,上述方法仅适用于直接运行脚本的场景。当资源文件被封装在 Python 包(package)内部,且通过外部模块调用该包内的 .py 文件时,直接读取文件名往往会失败。我们来验证这一情况:

此时 Python 解释器将无法定位文件。原因在于,入口脚本 main.py 位于 ~/get_title 目录下,而目标资源文件 test.txt 实际存放在 ~/get_title/util 子目录中。由于执行的是 main.py,Python 默认在当前工作目录(即 ~/get_title)下查找 test.txt,因此无法找到位于子目录中的文件。

对于包内其他 Python 模块的引用,可以使用相对路径,例如通过 from .sql_util import conn 导入同一包下的 conn 对象。但需要注意的是,资源文件不能直接通过相对路径读取,具体表现如下:

基于 os.path 的路径拼接方案

一种可行的替代方案是获取当前执行代码所在的目录路径,并手动拼接资源文件的绝对路径。修改 read.py 文件如下:


import os 
def read_file(): 
  current_folder = os.path.dirname(__file__) 
  resource_path = os.path.join(current_folder, 'test.txt') 
  with open(resource_path) as f: 
    content = f.read() 
  print('文件中的内容为:', content) 

运行效果如下图所示:

尽管该方法可行,但代码编写较为繁琐。

Python 3.7+ 推荐方案:importlib.resources

若你的 Python 环境版本不低于 3.7,推荐使用 importlib.resources 模块来高效读取资源文件:


from importlib import resources 
with resources.open_text('包名', '资源路径') as f: 
  content = f.read() 

运行效果如下图所示:

若需读取非文本类型的资源文件,可将 resources.open_text 替换为 resources.open_binary,以支持二进制文件的读取。

需特别注意,使用此方法时资源文件必须位于包的根目录下才能被正确识别。若资源文件存放在包内部的子目录中,importlib.resources 无法直接访问该子目录下的文件。

处理嵌套子目录中的资源文件

例如,假设包名为 util,其内部包含一个名为 deep_folder 的子文件夹,且资源文件 test.txt 位于 deep_folder 中。此时,若要读取该文件,必须在 deep_folder 目录下创建 __init__.py 文件,使其成为一个独立的子包。随后修改 read.py 的代码:


from importlib import resources 
from . import deep_folder 

def read_file(): 
  with resources.open_text(deep_folder, 'test.txt') as f: 
    content = f.read() 
  print('文件中的内容为:', content) 

将 deep_folder 作为模块导入,并将其作为 resources.open_text 的第一个参数传入,即可正确读取资源文件,效果如下:

以上内容涵盖了 Python 读取资源文件的核心要点,希望能为各位开发者提供实用参考,欢迎继续支持本站获取更多信息。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表