专栏首页快乐学Python在Python中按路径读取数据文件的几种方式

在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可以大大简化读取包里面的数据文件的代码。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 安迪带你快速开始python玩耍

    这里是一份近期的教程总纲。将会在这里和大家分享我近一年陆陆续续的学习历程和收获。有磕绊、有迷茫,也走了不少弯路。于是说干就干写个教程,希望能帮助后来的人。

    马哥Python
  • Python 连接 MySQL 的几种姿势

    尽管很多 NoSQL 数据库近几年大放异彩,但是像 MySQL 这样的关系型数据库依然是互联网的主流数据库之一,每个学 Python 的都有必要学好一门数据库,...

    马哥Python
  • git commit之后,想撤销commit

    意思是:不删除工作空间改动代码,撤销commit,并且撤销git add . 操作

    马哥Python
  • 从马斯洛理论看苹果公司的“果粉”成长历程

    用户1756920
  • 我在工作中的常用代码管理

    说是管理其实就是把常用的一些JS方法,自己保存下来,这样的以后的工作中可以比较方便的使用。 哪些方法可以、或是说值得保存呢?(偏见啊)我自己的主观看法就是一些功...

    web前端教室
  • 函数模板之名为List的类模板—C++

    汐楓
  • 作为TensorFlow的底层语言,你会用C++构建深度神经网络吗?

    机器之心
  • Web前端-Vue.js必备框架(二)

    mustache插值和v-bind表达式。 vue生命周期,从创建,运行,到销毁,称为生命周期。

    达达前端
  • 【学术】在C ++中使用TensorFlow训练深度神经网络

    你可能知道TensorFlow的核心是用C++构建的,然而只有python的API才能获得多种便利。 当我写上一篇文章时,目标是仅使用TensorFlow的C ...

    AiTechYun
  • 寿司快卖,创建一个运行在电脑,手机及Pad上的多屏游戏

    本节开始,我们将设计一个养成类游戏。游戏主题是创建一家寿司店,你是主厨,当客户点餐后,你根据菜单配置寿司。我们会先把游戏设计成页面游戏,然后通过不断的调试,将游...

    望月从良

扫码关注云+社区

领取腾讯云代金券