一日一技:Python讀取包裏面的數據文件的三種方法ide
咱們知道,寫Python代碼的時候,若是一個包(package)裏面的一個模塊要導入另外一個模塊,那麼咱們可使用相對導入:函數
假設當前代碼結構以下圖所示:spa
其中 test_1是一個包,在util.py裏面想導入同一個包裏面的 read.py中的 read函數,那麼代碼能夠寫爲:3d
from .read import read def util(): read()
其中的 .read表示當前包目錄下的 read.py文件。此時 read.py文件中的內容以下:code
def read(): print('閱讀文件')
經過包外面的main.py運行代碼,運行效果以下圖所示:blog
如今,咱們增長一個數據文件, data.txt,它的內容以下圖所示:圖片
而且想經過read.py去讀取這個數據文件並打印出來。utf-8
修改read.py,試圖使用相對路徑來打開這個文件:字符串
def read(): with open('./data.txt', encoding='utf-8') as f: text = f.read() print(text)
運行代碼發現報錯:get
這個緣由很簡單,就是若是數據文件的地址寫爲: ./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)
運行效果以下圖所示:
先獲取 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)
運行效果以下圖所示:
import pkgutil
def read():
data_bytes = pkgutil.get_data(package, 'data.txt')
data_str = data_bytes.decode()
print(data_str)
運行效果以下圖所示:  pkgutil是Python自帶的用於包管理相關操做的庫, pkgutil能根據包名找到包裏面的數據文件,而後讀取爲bytes型的數據。若是數據文件內容是字符串,那麼直接 decode()之後就是正文內容了。 使用 pkgutil還有一個好處,就是隻要知道包名就能夠找到對應包下面的數據文件,數據文件並不必定要在當前包裏面。 例如修改代碼結構以下圖所示:  另外一個包 test_2裏面有一個數據文件 data2.txt。此時若是要在 teat_1包的 read.py中讀取 data2.txt中的內容,那麼只須要修改 pkgutil.get_data的第一個參數爲 test_2,第二個參數爲數據文件的名字便可,運行效果以下圖所示:  而前兩種方法都不如 pkgutil簡單。 因此使用 pkgutil能夠大大簡化讀取包裏面的數據文件的代碼。 > 封面圖片做者:產品經理 kingname