在Python中按路径读取数据文件的几种方式
我们知道,写Python代码的时候,如果一个包(package)里面的一个模块要导入另一个模块,那么我们可以使用相对导入:
假设当前代码结构如下图所示:
img
其中test_1
是一个包,在util.py里面想导入同一个包里面的read.py
中的read
函数,那么代码可以写为:
from .read import read
def util():
read()
其中的.read
表示当前包目录下的read.py
文件。此时read.py
文件中的内容如下:
def read():
print('阅读文件')
通过包外面的main.py运行代码,运行效果如下图所示:
img
现在,我们增加一个数据文件,data.txt
,它的内容如下图所示:
img
并且想通过read.py去读取这个数据文件并打印出来。
修改read.py,试图使用相对路径来打开这个文件:
def read():
with open('./data.txt', encoding='utf-8') as f:
text = f.read()
print(text)
运行代码发现报错:
img
这个原因很简单,就是如果数据文件的地址写为:./data.txt
,那么Python就会从当前工作区文件夹里面寻找data.txt
。由于我们运行的是main.py
,那么当前工作区就是main.py
所在的文件夹,而不是test_1
文件夹。所以就会出现找不到文件的情况。
为了解决这个问题,我们有三种解决方式。
- 使用绝对路径
def read():
with open('/Users/kingname/Project/DataFileExample/test_1/data.txt', encoding='utf-8') as f:
text = f.read()
print(text)
运行效果如下图所示:
img
- 先获取
read.py
文件的绝对路径,再拼接出数据文件的绝对路径:
import os
def read():
basepath = os.path.abspath(__file__)
folder = os.path.dirname(basepath)
data_path = os.path.join(folder, 'data.txt')
with open(data_path, encoding='utf-8') as f:
text = f.read()
print(text)
运行效果如下图所示:
img
- 使用pkgutil库
import pkgutil
def read():
data_bytes = pkgutil.get_data(__package__, 'data.txt')
data_str = data_bytes.decode()
print(data_str)
运行效果如下图所示:
img
pkgutil
是Python自带的用于包管理相关操作的库,pkgutil
能根据包名找到包里面的数据文件,然后读取为bytes型的数据。如果数据文件内容是字符串,那么直接decode()
以后就是正文内容了。
为什么pkgutil读取的数据文件是bytes型的内容而不直接是字符串类型? 这是因为并不是所有数据文件都是字符串,如果某些数据文件是二进制文件或者图片,那么以字符串方式打开就会导致报错。所以为了通用,pkgutil会以bytes型方式读入数据,这相当于open函数的“rb”读取方式。
使用pkgutil
还有一个好处,就是只要知道包名就可以找到对应包下面的数据文件,数据文件并不一定要在当前包里面。
例如修改代码结构如下图所示:
img
另一个包test_2
里面有一个数据文件data2.txt
。此时如果要在teat_1
包的read.py
中读取data2.txt
中的内容,那么只需要修改pkgutil.get_data
的第一个参数为test_2
和数据文件的名字即可,运行效果如下图所示:
img
而前两种方法都不如pkgutil
简单。
所以使用pkgutil
可以大大简化读取包里面的数据文件的代码。
- 依赖注入(IOC)二
- Linux Token Auth 一次性密码认证
- WPF备忘录(7)WPF图片资源路径介绍
- 植入式攻击入侵检测解决方案
- 神经网络太臃肿?教你如何将神经网络减小四分之一
- WPF中ListView如何改变选中条背景颜色
- WPF Trigger for IsSelected in a DataTemplate for ListBox items
- C#基础知识回顾--BackgroundWorker介绍
- Elasticsearch 瞬间入门
- 使用OpenLDAP 操作 Windows Active Directory
- 优化算法:到底是数学还是代码?
- Email 服务器之 SPF 记录
- WPF中播放声音媒体文件
- 设计模式学习--装饰者模式(Decorator Pattern)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Backtracking - 39. Combination Sum
- Backtracking - 77. Combinations
- Backtracking - 90. Subsets II
- Backtracking - 78. Subsets
- Tree - 331. Verify Preorder Serialization of a Binary Tree
- Tree - 95. Unique Binary Search Trees II
- Tree - 96. Unique Binary Search Trees
- Tree - 116. Populating Next Right Pointers in Each Node
- Tree - 297. Serialize and Deserialize Binary Tree
- 使用 shell 脚本批量创建用户详解讲解
- Tree - 230. Kth Smallest Element in a BST
- Tree - 173. Binary Search Tree Iterator
- Tree - 450. Delete Node in a BST
- Tree - 687. Longest Univalue Path
- DFS - 980. Unique Paths III