在平時的開發中感覺INI格式的配置文件使用還是挺需要的,有時會使用一個單獨的py來存放一些常量或者配置項,大多時候這樣倒是挺好用的,但是如果某些配置項需要在運行時由用戶來修改指定,比如很多app在關閉時會有一個彈出框提示“是否關閉”和“下次不再提醒”,這種配置項如果使用INI格式的配置文件來操作的話就會方便很多,Python中操作配置文件的模塊為configparser,這個模塊可以用來解析與Windows上INI文件結構類似的文件。
官方文檔:https://docs.python.org/3/library/configparser.html
看官方文檔的時候發現不同Python版本之間某些API還是有些小區別的,所以先說一下,本文使用的是Python3.6。
一個普通的INI配置文件cfg.ini示例如下:
; DEFAULT為默認section,當獲取其他section中同名option,而該section又沒有這個option時,會取DEFAULT中的該option [DEFAULT] close_prompt = yes [baidu] website = www.baidu.com # 本機信息 [home] ip = 127.0.0.1 port = 8080
INI配置文件組成:
- section:表示一個區塊,由方括號及方括號中的名稱組成,section的范圍為當前方括號到下一個方括號的內容,如“DEFAULT”,“baidu”,“home”。
- 大小寫和空格檢查:section中的名稱在保存和獲取的時候是原樣保存和獲取的,即大小寫不一樣或者空格不一樣等都是不同的section;
- 重復性檢查:同一個配置文件中section名稱是不允許重復的。
- option:表示section中的配置項,由key、分隔符和value組成的鍵值對,如“home”下的“port=8080”。
- 大小寫檢查:key是大小寫不敏感的,保存進文件的時候會自動將key小寫保存,但value是大小寫敏感的;
- 空格檢查:通過key獲取value時,會自動將文件中的key和value前后空格去掉再進行匹配,即文件中保存為' ip = 127.0.0.1 '時,用'ip'也可以獲取到對應的value值'127.0.0.1';
- 跨多行檢查:key是不能跨行的,但是value可以跨行,只要第二行即之后的行的縮進與第一行不同即可,一直到下一個option為止;
- 重復性檢查:和section一樣,同一section下的key是不允許重復的;
- 分隔符:可以是等號“=”或者冒號“:”。
- 注釋:行注釋用井號“#”或者分號“;”表示,特別需要注意的是必須得是行開頭(前面可以有空格),用在行中間的就不會算作是注釋了。
- DEFAULT:這是一個特殊的section,會用作其他section的option取不到值時的備用值,或者可以理解為它是一個root,其他的section都是它的子section,但不是必須提供的。
向配置文件中寫數據:
# -*- coding:utf-8 -*- from configparser import ConfigParser # 使用字典的方式給配置對象添加配置信息 config = ConfigParser() config['DEFAULT'] = { 'close_prompt': 'yes', } config['baidu'] = {} config['baidu']['website'] = 'www.baidu.com' config['home'] = {} home = config['home'] home['ip'] = '127.0.0.1' home['port'] = '8080' # 將配置信息寫入文件 with open('cfg.ini', 'w') as cfg_file: config.write(cfg_file)
從配置文件中讀取數據:
# -*- coding:utf-8 -*- from configparser import ConfigParser # 以字典的方式讀取配置對象中的數據 config = ConfigParser() print(config.sections()) # 輸出:[] # 從配置文件中讀取數據,如果配置文件中有中文信息,注意編碼 config.read('cfg.ini', encoding='utf-8') print(config.sections()) # 輸出:['baidu', 'home'] print('baidu' in config) # 輸出:True print(config['baidu']['website']) # 輸出:www.baidu.com home = config['home'] print(home['ip']) # 輸出:127.0.0.1 for key in home: print(key) # 依次輸出:ip,port,close_prompt
configparser.ConfigParser
從上面的例子可以看出ConfigParser實例可以像操作字典一樣去操作它,每個section對應一個由key/value組成的option字典,雖然可以通過添加和設置section和option等方法來操作,但還是推薦使用字典的方式,可讀性也要強一點。其實還有另一個解析類RawConfigParser,與ConfigParser的區別在於前者不允許進行字符串的格式化,而且后者也是繼承自前者的,所以這里就只講ConfigParser。(至於還有一個SafeConfigParser,在Python3.2之后就合道ConfigParser中,跟RawConfigParser和ConfigParser的區別在於可以跨section進行字符串的格式化,這里也不講了)
初始化方法:ConfigParser(defaults=None, dict_type=_default_dict, allow_no_value=False, *, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section=DEFAULTSECT, interpolation=_UNSET, converters=_UNSET):
- defaults:設置配置文件中名為DEFAULT的默認section信息,默認為None,可以傳入一個包含option信息的字典;
- dict_type:設置讀取配置信息時的字典類型,默認為有序字典,即collections.OrderedDict,如果實在要考慮性能等原因,可以使用python默認字典dict;
- allow_no_value:是否允許key沒有對應的value,默認為False,如果加載的配置文件中有這種情況,需要手動設置為True;
- delimiters:設置分隔符,默認為“=”和“:”,且一個option中第二個及之后的分隔符會算作value的一部分;
- comment_prefixes:設置注釋符,默認為“#”和“;”,即一行的開頭(取出空格后)為“#”或者“;”,則這一行算作注釋內容,包括value有多行的情況也是如此;
- inline_comment_prefixes:設置行中的注釋前綴,即一行中這個符號之后的內容被認為是注釋;
- strict:默認為True,即讀取配置數據時不允許出現重復的section和option;
- empty_lines_in_values:是否允許value中出現空行,默認為True,如果設置為False,則value中的空行將作為這個option的結束標志;
- default_section:更改默認的section名稱,原本默認的section是DEFAULT(注意更改操作需要在實例化之后,讀取數據之前);
- interpolation:設置value的字符串格式化功能,如果不想使用value的字符串格式化功能,可以設置None;
- converters:設置將value轉換為特定類型的數據,參數值為一個字典,字典的key為轉換方法的名稱,value為對應的轉換函數,提供這個字典后,會自動生成對應的get/set方法,比如提供一個字典{'int': int}就會生成getint轉換方法(當然這個方法已經內置有了,這里只是舉個例子)。
value字符串格式化:可以使用%(name)s進行字符串的格式化,且name只能是本section和DEFAULT中的option項。
自定義option的key配置方式:如原本是key是自動轉化為小寫的,現在設置其區分大小寫:parser.optionxform = lambda option: option(注意更改操作需要在實例化之后,讀取數據之前)。
自定義section自定義配置方式:如原本section是包含了空格以及大小寫區分的,現在利用正則表達式設置其去掉首位的空格:parser.SECTCRE = re.compile(r"\[ *(?P<header>[^]]+?) *\]")(注意更改操作需要在實例化之后,讀取數據之前)。
常用方法:
- defaults():以字典的方式返回默認的section,即DEFAULT;
- sections():返回section名稱的列表,但是不包括DEFAULT;
- add_section(section):添加一個section,字符串類型,且已經存在的section不能再往里添加;
- has_section(section):判斷當前配置中是否有此section,DEFAULT不包含在此判斷中;
- options(section):返回此section下的option列表;
- has_option(section, option):如果指定的section存在,且包含該option,則返回True,否則返回False;如果傳入的section為None或者空字符串,則使用DEFAULT這個section進行查找判斷;
- read(filenames, encoding=None):可以傳入單個文件,或者多個文件的列表,如果多個文件中某個文件無法打開,則這個文件會被忽略;
- read_file(f, source=None):從一個文件流(不是文件名稱)讀取配置,source為文件流的名稱;
- read_string(string, source='<string>'):從一個字符串讀取配置,source為字符串的名稱;
- read_dict(dictionary, source='<dict>'):從一個類字典對象中讀取配置信息,source為類字典對象的名稱;
- get(section, option, *, raw=False, vars=None[, fallback]):獲取section下指定option的值,如果vars被提供了(必須是一個字典),則按照vars、section、DEFAULT這個順序進行查找。raw指定為True時,option中value值不會自動進行格式化字符串的轉換,直接返回原內容。fallback用於指定當查找的option沒有時返回的默認值;
- getint(section, option, *, raw=False, vars=None[, fallback]):將get的值強轉成int類型(raw、vars和fallback參數請參考get方法);
- getfloat(section, option, *, raw=Fasle, vars=None[, ballback]):將get的值強轉成float類型(raw、vars和fallback參數請參考get方法);
- getboolean(section, option, *, raw=False, vars=None[, fallback]):將get的值強轉成boolean類型True或False,轉換原則為yes/no、on/off、true/false和1/0可以轉換為True和False,其他項則會報錯(raw、vars和fallback參數請參考get方法)。如果想要自定義轉換為True或False的項,可以通過設置parser.BOOLEAN_STATES來定指定,如:parser.BOOLEAN_STATES = {'open': True, 'close': False},但是這時候意味着沒在這個字典中的項就會報錯了,包括原來的yes/no等項;
- items((raw=False, vars=None):返回section的迭代器,包括DEFAULT(raw和vars參數請參考get方法);
- items(section, raw=False, vars=None):返回指定section下option鍵值對元組的列表(raw和vars參數請參考get方法);
- set(section, option, value):給指定的section設置一個option鍵值對;
- write(fileobject, space_around_delimiters=True):將配置信息寫進一個open的文件對象,space_around_delimiters為True時,option的分隔符兩邊會有空格;
- remove_option(section, option):移除指定section下的指定option,成功返回True,否則返回False;
- remove_section(section):移除一個section,如果存在且移除成功,則返回True,否則返回False。