天天看點

最全總結 | 聊聊 Python 資料處理全家桶(配置篇)

1.前言

在實際項目中,經常會接觸到各種各樣的配置檔案,它可以增強項目的可維護性

常用配件檔案的處理方式,包含:JSON、ini / config、YAML、XML 等

本篇文章,我們将聊聊 Python 資料處理全家桶之配置檔案大總結

​2.JSON

Python 内置了 JSON 子產品,可以非常友善操作 JSON 資料

常見的 4 個方法分别是:

  • json.load(json_file)

    解析 JSON 檔案,轉換為 Python 中對應的資料類型

  • json.loads(json_string)

    解析 JSON 格式的字元串,結果為 Python 中的字典

  • json.dump(python_content,file_path)

    将 Python 資料,包含:dict、list 寫入到檔案中

  • json.dumps(python_dict)

    将 Python 中 dict 轉為 JSON 格式的字元串

以下面這段 JSON 配置檔案為例:

#config.json
{
  "mysql": {
    "host": "198.0.0.1",
    "port": 3306,
    "db": "xh",
    "username": "root",
    "password": "123456",
    "desc": "Mysql配置檔案"
  }
}
           

1、讀取配置檔案

讀取配置檔案有兩種方式,分别是:

使用 json.load() 直接讀取配置檔案

或者,先讀取配置檔案中的内容,然後使用 json.loads() 轉換為 Python 資料類型

需要指出的是,面對複雜層級的 JSON 配置檔案,可以利用 jsonpath 進行讀取;jsonpath 類似于 xpath,可以通過正規表達式快速讀取資料

import json

def read_json_file(file_path):
    """
    讀取json檔案
    :param file_path:
    :return:
    """
    with open(file_path, 'r', encoding='utf-8') as file:

        # 讀取方式二選一
        # 方式一
        result = json.load(file)

        # 方式二
        # result = json.loads(file.read())

        # 解析資料
        host_mysql = result['mysql']['host']
        port_mysql = result['mysql']['port']
        db = result['mysql']['db']

        print('Mysql位址:', host_mysql, ",端口号:", port_mysql, ",資料庫:", db)
​
    return result
           

2、儲存配置檔案

使用 json 中的 json.dump() 方法,可以将一個字典寫入到 JSON 檔案中

def write_content_to_json_file(output_file, content):
    """
    寫入到json檔案中
    :param output_file:
    :param content:
    :return:
    """
    with open(output_file, 'w') as file:
        # 寫入到檔案中
        # 注意:為了保證中文能正常顯示,需要設定ensure_ascii=False
        json.dump(content, file, ensure_ascii=False)

content_dict = {
    'mysql': {
        'host': '127.0.0.1',
        'port': 3306,
        'db': 'xh',
        'username': 'admin',
        'password': '123456',
        'desc': 'Mysql資料庫'
    }
}

write_content_to_json_file('./output.json', content_dict)
           

3、修改配置檔案

如果需要修改配置檔案,隻需要先從配置檔案中讀出内容,然後修改内容,最後将修改後的内容儲存的配置檔案中即可

def modify_json_file():
    """
    修改json配置檔案
    :return:
    """
    result = read_json_file('./config.json')

    # 修改
    result['mysql']['host'] = '198.0.0.1'

    write_content_to_json_file('./config.json', result)
           

3.ini/config

ini 配置檔案和 config 配置檔案的解析方式類似,僅僅是檔案字尾不一緻

這裡我們以 ini 配置檔案為例

# config.ini
[mysql]
host = 139.199.1.1
username = root
password = 123456
port = 3306
           

ini 檔案由 3 部分組成,分别是:節點(Section)、鍵(Key)、值(Value)

常見的 Python 處理 ini 檔案有兩種方式,包含:

  • 使用内置的 configparser 标準子產品
  • 使用 configobj第三方依賴庫

我們先來看看内置的 configparser 子產品

3.1.1 讀取配置檔案

執行個體化一個 ConfigParser 解析對象,使用 read() 方法讀取 ini 配置檔案

from configparser import ConfigParser

# 執行個體化解析對象
cfg = ConfigParser()

# 讀取ini檔案内容
cfg.read(file_path)
           

使用 sections()函數,可以擷取所有的節點清單

# sections() 得到所有的section,并以清單的形式傳回
sections = cfg.sections()
print(sections)
           

要擷取某一個節點下的所有鍵,可以使用 options(section_name) 函數

# 擷取某一個區域的所有key
# cfg.options(section_name)
keys = cfg.options('mysql')
print(keys)
           

通過 items(section_name) 函數,可以擷取某一個節點下的所有鍵值對

# 擷取某一個區域下的鍵值對
items = cfg.items("mysql")
print(items)
           

如果要擷取某一個節點下,某一個鍵下的值,使用 get(section_name,key_name) 函數即可

# 讀取某一個區域下的某一個鍵值
host = cfg.get("mysql", "host")
print(host)
           

3.1.2 寫入配置檔案

和讀取配置檔案類似,需要先執行個體化一個 ConfigParser 解析對象

首先,使用 add_section(section_name) 函數添加一個節點

# 加入節點和鍵值對
# 添加一個節點
cfg.add_section("redis")
           

然後,就可以使用 set(section_name,key,value) 函數往某一個節點添加鍵值對

# 往節點内,添加鍵值對
cfg.set("redis", "host", "127.0.0.1")
cfg.set("redis", "port", "12345")
           

最後,使用 write() 函數寫入到配置檔案中去

# 寫入到檔案中
cfg.write(open('./raw/output.ini', 'w'))
           

3.1.3 修改配置檔案

修改配置檔案的步驟是,讀取配置檔案,然後通過 set(section_name,key,value) 進行修改操作,最後使用 write() 函數寫入到檔案中即可

def modify_ini_file(file_path):
    """
    修改ini檔案
    :return:
    """
    cfg.read(file_path)

    cfg.set("mysql", "host", "139.199.11.11")

    # 寫入
    cfg.write(open(file_path, "w"))
           

接着,我們聊聊使用 configobj 操作 ini 配置檔案的流程

首先安裝 configobj 依賴庫

# 依賴
# pip3 install configobj
           

3.2.1 讀取配置檔案

直接将 ini 配置檔案路徑作為參數,使用 ConfigObj 類構造一個對象

from configobj import ConfigObj

# 執行個體化對象
config = ConfigObj(file_path, encoding='UTF8')
           

檢視源碼可以發現,ConfigObj 是 Section 節點的子類,而 Section 是 Dict 字典的子類

是以,可以直接通過鍵名 Key 擷取節點和鍵值

# <class 'configobj.ConfigObj'>
print(type(config))

# <class 'configobj.Section'>
print(type(config['mysql']))

# 節點
print(config['mysql'])

# 某一個鍵對應的值
print(config['mysql']
           

3.2.2 修改配置檔案

隻需要讀取配置檔案,然後直接修改 ConfigObj 對象,最後使用 write() 方法,即可以達到修改配置檔案的目的

def modify_ini_file(file_path):
    """
    修改ini檔案
    :param file_path:
    :return:
    """
    # 讀取配置檔案
    config = read_ini_file(file_path)

    # 直接修改
    config['mysql']['host'] = '139.199.1.1'

    # 删除某個鍵值對
    try:
        del config['mysql']['db']
    except Exception as e:
        print('鍵不存在')
        pass

    # 寫入
    config.write()
           

3.2.3 寫入配置檔案

寫入配置檔案,首先需要執行個體化一個 ConfigObj 對象,傳入檔案路徑

然後,設定節點、針對節點設定鍵值對

最後,調用 write() 方法,寫入到配置檔案中

def write_to_ini_file(output):
    """
    寫入到ini檔案中
    :param output:
    :return:
    """
    config = ConfigObj(output, encoding='UTF8')
    config['website'] = {}
    config['website']['url'] = "www.baidu.com"
    config['website']['name'] = "百度"

    # 儲存
    config.write()
           

4.YAML

Python 操作 YAML 檔案,常見的 2 種方式分别是:pyyaml、ruamel.yaml

使用 pip 安裝依賴

# 安裝依賴
# 方式一
pip3 install pyyaml

# 方式二
pip3 install ruamel.yaml
           

下面以一個簡單的 YAML 配置檔案為例,通過兩種方式進行說明

# 水果
Fruits:
  # 蘋果
  - Apple:
      name: apple
      price:  1
      address:  廣東
  # 桔子
  - Orange:
      name: orange
      price:  3
      address:  湖南
  # 香蕉
  - Banana:
      name: banana
      price:  2
      address:  海南
           

我們先來看看 pyyaml

4.1.1 讀取配置檔案

首先,讀取配置檔案,使用 yaml.safe_load() 加載資料,擷取的資料類型是字典

import yaml

with open(file_path, "r") as file:
    data = file.read()

    # safe_load() 讀取配置檔案
    # 結果資料類型:dict
    result = yaml.safe_load(data)

    print(result)
           

接着,就可以通過 YAML 配置檔案的層級關系,擷取鍵值

# 3、擷取yaml中的值
name = result['Fruits'][0]['Apple']['name']
price = result['Fruits'][0]['Apple']['price']
address = result['Fruits'][0]['Apple']['address']
print("名稱:", name, ",price:", price, ",address:", address)
           

4.1.2 寫入配置檔案

使用 YAML 中的 dump() 方法,可以将一個字典寫入到 YAML 配置檔案中

需要注意的是,為了保證中文寫入能正常顯示,需要配置 allow_unicode=True

def write_to_yaml_file(content, file_path):
    """
    寫入到yaml檔案中
    :param content:
    :param file_path:
    :return:
    """

    # 寫入到檔案中
    with open(file_path, 'w', encoding='utf-8') as file:
        yaml.dump(content, file, default_flow_style=False, encoding='utf-8', allow_unicode=True)

# 定義一個字典
content = {
   "websites": [{"baidu": {'url': "www.baidu.com", 'name': '百度', "price": 100}},{"alibaba": {'url': "www.taobao.com", 'name': '淘寶', "price": 200}},{"tencent": {'url': "www.tencent.com", 'name': '騰訊', "price": 300}},]
}

write_to_yaml_file(content, "./raw/new.yaml")
           

4.1.3 修改配置檔案

和修改 ini 檔案類型,先讀取配置檔案,然後修改字典中的内容,最後使用上面的寫入方法,即可以達到修改配置檔案的目的

def modify_yaml_file():
    """
    修改yaml檔案
    :return:
    """
    content = read_yaml_file('./raw/norm.yaml')
    print(content)

    # 修改dict
    content['Fruits'][0]['Apple']['price'] = 10086

    # 重新寫入到一個新的yaml檔案中
    write_to_yaml_file(content, './raw/output.yaml')
           

接着,我們來聊聊使用 ruamel 操作 YAML 配置檔案的流程

ruamel 是 pyyaml 的衍生版本,在傳統 pyyaml 的基礎上,增加了 RoundTrip 模式,保證 YAML 配置檔案的讀寫順序一緻

是以,在讀取、修改、寫入方式上和 pyyaml 類似

4.2.1 讀取配置檔案

from ruamel import yaml

def read_yaml_file(file_path):
    """
    讀取yaml檔案
    :param file_path:
    :return:
    """
    with open(file_path, 'r', encoding='utf-8') as file:
        data = file.read()

        # 解析yaml檔案
        # 類型:ordereddict
        result = yaml.load(data, Loader=yaml.RoundTripLoader)

        name = result['Fruits'][0]['Apple']['name']
        price = result['Fruits'][0]['Apple']['price']
        address = result['Fruits'][0]['Apple']['address']
        print("名稱:", name, ",price:", price, ",address:", address)

    return result
           

4.2.2 寫入配置檔案

def write_to_yaml_file(filepath, data):
    """
    寫入到yaml檔案中
    :param filepath:
    :param data:
    :return:
    """
    with open(filepath, 'w', encoding='utf-8') as file:
        yaml.dump(data, file, Dumper=yaml.RoundTripDumper, allow_unicode=True)
           

4.2.3 修改配置檔案

def modify_yaml_file():
    """
    修改yaml檔案
    :return:
    """
    content = read_yaml_file('./raw/norm.yaml')

    print(content)

    # 修改dict
    content['Fruits'][0]['Apple']['price'] = 10086

    # 重新寫入到一個新的yaml檔案中
    write_to_yaml_file('./raw/output.yaml', content)
           

5.XML

XML 作為一種标記語言,被用來設計存儲和傳輸資料,很多項目經常使用 XML 作為配置檔案和資料傳輸類型

Python 内置的 xml 子產品 可以很友善地處理 XML 配置檔案

以下面這段配置檔案為例:

<?xml version="1.0" encoding="utf-8"?>
<dbconfig>
    <mysql>
        <host>127.0.0.1</host>
        <port>3306</port>
        <dbname>test</dbname>
        <username>root</username>
        <password>4355</password>
    </mysql>
</dbconfig>
           

首先,使用 xml.dom.minidom.parser(file_path) 解析配置檔案,利用 documentElement 屬性擷取 XML 根節點

import xml.dom.minidom

# 讀取配置檔案
dom = xml.dom.minidom.parse("./raw.xml")

# 利用 documentElement 屬性擷取 XML 根節點
# 根節點
root = dom.documentElement
           

接着,使用 getElementsByTagName(tag_name) 方法,擷取某一節點

# 擷取mysql節點
node_mysql = root.getElementsByTagName('mysql')[0]
           

最後,使用 childNodes 屬性,周遊節點的子 Node 節點,擷取節點的名稱和值

# 周遊子節點,擷取名稱和值
for node in node_mysql.childNodes:
    # 節點類型
    # 1:Element
    # 2:Attribute
    # 3:Text
    # print(node.nodeType)
    if node.nodeType == 1:
        print(node.nodeName, node.firstChild.data)
           

6.最後

到此,Python 資料全家桶以全部完結!

我已經将文中全部源碼上傳到背景,關注公衆号「 AirPython 」後回複「 dball 」即可獲得全部源碼

如果你覺得文章還不錯,請大家 點贊、分享、留言下,因為這将是我持續輸出更多優質文章的最強動力!

推薦閱讀

聊聊 Python 資料處理全家桶(Mysql 篇)

聊聊 Python 資料處理全家桶(Sqlite 篇)

聊聊 Python 資料處理全家桶(Redis 篇)

聊聊 Python 資料處理全家桶(Memc 篇)

聊聊 Python 資料處理全家桶(Mongo 篇)

分享 Python 自動化及爬蟲、資料分析實戰幹貨,歡迎關注。