Python 更加优雅的读取资源方式 importlib.resources

1. 简介

这个模块使得Python的导入系统提供了访问*包*内的*资源*的功能。如果能够导入一个包,那么就能够访问那个包里面的资源。资源可以以二进制或文本模式方式被打开或读取。

Python项目使用项目内的资源文件,例如项目所需的数据文件。通常使用以下方法

  1. 硬编码数据文件的路径
  2. 将数据文件放入包装中,并使用进行定位__file__
  3. 使用setuptools.pkg_resources访问数据文件资源

如  项目文件结构如下, 在test.py 中要使用data.txt 中的数据

myproject/
├── package/
│   ├── __init__.py
│   ├── tool.py
│   ├── data.txt
├── test.py

1.1 硬编码文件路径

使用最直接的方法, open函数,传入data.txt文件的路径,即可访问文件。

# test.py

with open('package/data.txt', 'r') as f:
    text = f.read()
    print(text)

问题是, 由于是采用相对路径, 如果在其他路径执行test.py  的代码, (如在父目录中) 就会报错

❯ python ./myproject/test_resource.py
FileNotFoundError: [Errno 2] No such file or directory: 'package/data.txt'

1.2 使用__file__定位,使用绝对路径

一种更加优雅的方式,是使用文件的__file__属性,定位到当前的路径, 结合pathlib,使用绝对路径访问目标文件。

import pathlib
PATH = pathlib.Path(__file__)

data_file = PATH.parent / 'package' /'data.txt'
print(data_file.read_text())

但是也有问题, 如果是一个大包的python应用, 它可能最终位于zip内并且没有__file__属性。

1.3 setuptools.pkg_resources

使用setuptools.pkg_resources 可以解决上述的问题, 但是缺点是很慢。

1.4 更好的解决方案

使用Python 3.7 引入标准库中的新模块 importlib.resources 可以解决以上问题。

这个模块使得Python的导入系统提供了访问*包*内的*资源*的功能。如果能够导入一个包,那么就能够访问那个包里面的资源。资源可以以二进制或文本模式方式被打开或读取。

代码如下:

import importlib.resources as res
import package

text = res.read_text(package, 'data.txt', encoding='utf-8', errors='strict')
print(text)

2. 函数介绍

① 前面使用了read_text,  importlib.resources 还有另一个方法 open_text, 以文本格式打开。 返回一个io对象, 效果同 open('package/data.txt', 'r')

datafile = res.open_text(package, 'data.txt', encoding='utf-8', errors='strict')
print(datafile.read())

② 对应的二进制打开的方法, open_binary 和  read_binary 。

③ 还有一个 contents 方法, 返回包内所有文件对象。

data = res.contents(package)
for con in data:
    print(con)

返回

data.txt
tool.py
__init__.py
__pycache__

④ path 方法, 此函数返回一个上下文管理器以用于 with 语句。 上下文管理器提供了一个 pathlib.Path 对象。

with res.path(package, 'data.txt') as datafile:
    print(datafile)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值