配置文件格式
配置文件(*.ini)的基本格式如下:
[device] type = NULL id = 1 [comn] protocol = 0 lenth = 400 filter_min = 120 filter_max = 400 [wifi] ssid = user_ssid_null psk = user_psk_null
[device]、[comn]、[wifi] 這些叫做 sections(節),每個section下面包含多個options(參數)/items(參數對,和字典的概念類似),例如:type = NULL,這里的“type”就叫做option,而(’type’, ‘NULL’)被稱為item。參數的值均是以string格式存儲的。
configparser庫
使用Python的configparser庫來讀寫配置文件,configparser官方文檔:
https://docs.python.org/3/library/configparser.html#configparser.ConfigParser
搜索ConfigParser Objects,這一節有函數詳細的功能介紹,下面列一部分常用的:
cf = configparser.ConfigParser() | 創建configparser實例 |
sections() | 返回sections的列表 |
add_section(section) | 增加一個section |
remove_section(section) | 刪除一個section |
has_section(section) | 返回某個section是否存在 |
options(section) | 返回某個section下的options列表 |
has_option(section, option) | 返回某個section下的某個option是否存在 |
remove_option(section, option) | 刪除某個section下的某個option |
items() | 獲得所有的sections,包括默認section |
items(section) | 獲得某個section下的所有items/參數對 |
read(filenames) | 讀取某個配置文件filenames,加載到ConfigParser實例 |
get(section, option) | 以string格式,返回某個section下的某個option的值 |
getint(section, option) | 以int格式,返回某個section下的某個option的值 |
getfloat(section, option) | 以float格式,返回某個section下的某個option的值 |
getboolean(section, option) | 以boolean格式,返回某個section下的某個option的值 |
set(section, option, value) | 設置某個section下的某個option的值 |
write(fileobject) | 將當前的ConfigParser實例寫入到配置文件fileobject |
生成配置文件
ConfigParser庫在Python2和Python3中有點區別:
- Python3
configparser庫的首字母小寫
import configparser
config = configparser.ConfigParser()
創建文件test_config_create_p3.py,復制下面的內容,保存退出
pi@raspberrypi:~ $ sudo nano test_config_create_p3.py
1 # -*- coding:utf-8 -*- 2 import configparser 3 4 config = configparser.ConfigParser() 5 6 config["device"] = { 7 'type' : 'NULL', 8 'id' : '1' 9 } 10 11 config["comn"] = { 12 'protocol' : '0', 13 'lenth' : '400', 14 'filter_min' : '50', 15 'filter_max' : '400' 16 } 17 18 config["wifi"] = { 19 'ssid' : 'user_ssid_null', 20 'psk' : 'user_psk_null' 21 } 22 23 with open('config.ini', 'w') as cf: 24 config.write(cf)
運行程序:
pi@raspberrypi:~ $ python3 test_config_create_p3.py
打開生成的配置文件config.ini:
pi@raspberrypi:~ $ sudo nano config.ini
sections和options的內容都是對的,只是section下的options的順序與預期的不一致,不過這樣也沒什么問題。
- Python2
ConfigParser庫的首字母大寫
import ConfigParser
config = ConfigParser.ConfigParser()
python2中只能逐條添加section和option
創建文件test_config_create_p2.py,復制下面的內容,保存退出
pi@raspberrypi:~ $ sudo nano test_config_create_p2.py
1 # -*- coding:utf-8 -*- 2 import ConfigParser 3 4 config = ConfigParser.ConfigParser() 5 6 config.add_section("device") 7 config.set("device", "type", 'NULL') 8 config.set("device", "id", '1') 9 10 config.add_section("comn") 11 config.set("comn", "protocol", '0' ) 12 config.set("comn", "lenth", '400') 13 config.set("comn", "filter_min", '50' ) 14 config.set("comn", "filter_max", '400' ) 15 16 config.add_section("wifi") 17 config.set("wifi", "ssid", 'user_ssid_null') 18 config.set("wifi", "psk", 'user_psk_null') 19 20 with open('config.ini', 'w') as cf: 21 config.write(cf)
先刪掉可能存在的config.ini文件
pi@raspberrypi:~ $ rm -f config.ini
運行程序:
pi@raspberrypi:~ $ python2 test_config_create_p2.py
打開生成的配置文件config.ini:
pi@raspberrypi:~ $ sudo nano config.ini
sections和options的內容都是對的,section下的options的順序與預期的一致。
讀取配置文件
讀取配置參數時,先確認section是否存在,如果不存在就添加section,並寫入默認配置參數。
這里使用的配置參數主要有兩種類型:string和int,分別使用get(section, option)、getint(section, option)去讀取參數。
讀取完成后把所有的items都打印出來。
1 def GetConfig(filepath): 2 global PRODUCT_TYPE 3 global DEVICE_ID 4 5 global PROTOCOL_TYPE 6 global DB_PARAMS_LENGTH 7 global COMN_FILTER_MIN 8 global COMN_FILTER_MAX 9 10 global WIFI_SSID 11 global WIFI_PASSWORD 12 13 is_new_section = False 14 15 print('>> GetConfig()...') 16 print(filepath) 17 18 config = configparser.ConfigParser() 19 config.read(filepath) 20 21 if "wifi" not in config.sections(): 22 print('>> add config >> wifi...') 23 is_new_section = True 24 config.add_section("wifi") 25 config.set("wifi", "ssid", WIFI_SSID) 26 config.set("wifi", "psk", WIFI_PASSWORD) 27 else: 28 WIFI_SSID = config.get("wifi", "ssid") 29 WIFI_PASSWORD = config.get("wifi", "psk") 30 31 if "device" not in config.sections(): 32 print('>> add config >> device...') 33 is_new_section = True 34 config.add_section("device") 35 config.set("device", "type", PRODUCT_TYPE) 36 config.set("device", "id", str(DEVICE_ID)) 37 else: 38 PRODUCT_TYPE = config.get("device", "type") 39 DEVICE_ID = config.getint("device", "id") 40 41 if "comn" not in config.sections(): 42 print('>> add config >> comn...') 43 is_new_section = True 44 config.add_section("comn") 45 config.set("comn", "protocol", str(PROTOCOL_TYPE) ) 46 config.set("comn", "lenth", str(DB_PARAMS_LENGTH)) 47 config.set("comn", "filter_min", str(COMN_FILTER_MIN) ) 48 config.set("comn", "filter_max", str(COMN_FILTER_MAX) ) 49 else: 50 PROTOCOL_TYPE = config.get("comn", "protocol") 51 DB_PARAMS_LENGTH = config.getint("comn", "lenth") 52 COMN_FILTER_MIN = config.getint("comn", "filter_min") 53 COMN_FILTER_MAX = config.getint("comn", "filter_max") 54 55 print('>> list config items...') 56 for sections in config.sections(): 57 for items in config.items(sections): 58 print(items) 59 60 if True == is_new_section: 61 print('>> new section added, write to config file...') 62 with open(filepath, 'w+') as cf: 63 config.write(cf)
修改配置文件
用set(section, option, value)來設置參數值,可以把所有參數值都用str()強制轉換一下。
寫入之前先把所有的items都打印出來。
1 def SetConfig(filepath): 2 global WIFI_SSID 3 global WIFI_PASSWORD 4 global PRODUCT_TYPE 5 global DEVICE_ID 6 global PROTOCOL_TYPE 7 global DB_PARAMS_LENGTH 8 global COMN_FILTER_MIN 9 global COMN_FILTER_MAX 10 11 print('>> SetConfig()...') 12 print(filepath) 13 14 config = configparser.ConfigParser() 15 config.read(CONFIG_FILE) 16 17 if "device" not in config.sections(): 18 config.add_section("device") 19 if "comn" not in config.sections(): 20 config.add_section("comn") 21 if "wifi" not in config.sections(): 22 config.add_section("wifi") 23 24 config.set("wifi", "ssid", str(WIFI_SSID)) 25 config.set("wifi", "psk", str(WIFI_PASSWORD)) 26 27 config.set("device", "type", str(PRODUCT_TYPE)) 28 config.set("device", "id", str(DEVICE_ID)) 29 30 config.set("comn", "protocol", str(PROTOCOL_TYPE) ) 31 config.set("comn", "lenth", str(DB_PARAMS_LENGTH)) 32 config.set("comn", "filter_min", str(COMN_FILTER_MIN) ) 33 config.set("comn", "filter_max", str(COMN_FILTER_MAX) ) 34 35 print('>> list config items...') 36 for sections in config.sections(): 37 for items in config.items(sections): 38 print(items) 39 40 print('>> write to config file...') 41 with open(CONFIG_FILE, 'w+') as cf: 42 config.write(cf)
運行測試
使用Python3進行測試(如果用Python2,只需要把庫的首字母改成大寫的)
創建測試程序test_config.py。SetConfig()、GetConfig()參考上面,這里為了便於閱讀省略了。
pi@raspberrypi:~ $ sudo nano test_config.py
這個測試函數里先是把默認的配置參數寫入到配置文件並讀取,然后再修改配置參數,重新寫入到配置文件並讀取。程序會打印即將寫入配置文件的參數,還有從配置文件中讀取到的參數。
1 # -*- coding:utf-8 -*- 2 import configparser 3 4 CONFIG_FILE = '/home/pi/config.ini' 5 6 PRODUCT_TYPE = 'NULL' 7 DEVICE_ID = 1 8 PROTOCOL_TYPE = 0 9 DB_PARAMS_LENGTH = 400 10 COMN_FILTER_MIN = 50 11 COMN_FILTER_MAX = 400 12 WIFI_SSID = 'user_ssid_null' 13 WIFI_PASSWORD = 'user_psk_null' 14 15 #---- 16 def GetConfig(filepath): 17 #### 18 19 #---- 20 def SetConfig(filepath): 21 #### 22 23 #---- 24 def main(): 25 global CONFIG_FILE 26 27 global WIFI_SSID 28 global WIFI_PASSWORD 29 global PRODUCT_TYPE 30 global DEVICE_ID 31 global PROTOCOL_TYPE 32 global DB_PARAMS_LENGTH 33 global COMN_FILTER_MIN 34 global COMN_FILTER_MAX 35 36 SetConfig(CONFIG_FILE) 37 GetConfig(CONFIG_FILE) 38 39 PRODUCT_TYPE = 'ANOTHER_TYPE' 40 DEVICE_ID = 2 41 42 PROTOCOL_TYPE = 1 43 DB_PARAMS_LENGTH = 300 44 COMN_FILTER_MIN = 100 45 COMN_FILTER_MAX = 300 46 47 WIFI_SSID = 'another_user_ssid_null' 48 WIFI_PASSWORD = 'another_user_psk_null' 49 50 SetConfig(CONFIG_FILE) 51 GetConfig(CONFIG_FILE) 52 53 if __name__ == '__main__': 54 main()
用Python3運行
pi@raspberrypi:~ $ python3 test_config.py