前言
使用配置文件來靈活的配置一些參數是一件很常見的事情,配置文件的解析並不複雜,在python裏更是如此,在官方發佈的庫中就包含有做這件事情的庫,那就是configParser
configParser解析的配置文件的格式比較象ini的配置文件格式,就是文件中由多個section構成,每個section下又有多個配置項
ConfigParser簡介
ConfigParser 是用來讀取配置文件的包。配置文件的格式如下:中括號“[ ]”內包含的爲section。section 下面爲類似於key-value 的配置內容。
ConfigParser
模塊在python3中修改爲configparser
.這個模塊定義了一個ConfigParser類,該類的作用是使用配置文件生效,配置文件的格式和windows的INI文件的格式相同
該模塊的作用 就是使用模塊中的RawConfigParser()
、ConfigParser()
、 SafeConfigParser()
這三個方法(三者擇其一),創建一個對象使用對象的方法對指定的配置文件做增刪改查 操作。
ini文件結構
ini文件結構需要注意一下幾點:
- 鍵值對可用
=
或者:
進行分隔 section
的名字是區分大小寫的,而key
的名字是不區分大小寫的- 鍵值對中頭部和尾部的空白符會被去掉
- 值可以爲多行
- 配置文件可以包含註釋,註釋以
#
或者;
爲前綴
注意:configparser有default_section的概念,默認爲[DEFAULT]
節,也就是之後的所有的section都有該默認section中的鍵值對,詳情參見configparser源碼的__init__()
方法
一、使用ConfigParser類解析ini配置文件
(PyCharm中實現)
實現查詢、添加、刪除、保存。
練習目的:
- 掌握文件基本操作
- 認識ini文件
- 瞭解ConfigParser類
使用ConfigParser類解析配置文件
ini配置文件的格式:
節: [session]
參數(鍵=值) name=value
1、解析mysql配置文件
**read(filename)
直接讀取文件內容**get(section, option)
獲取section
下具體某一配置項的值(返回的是字符串)sections()
得到所有的section,並以列表的形式返回options(section)
得到該section的所有optionitems(section)
鍵值對的形式 得到該section的所有optiongetint(section,option)
、cnf.getboolean(section,option)
、getfloat(section,option)
獲取整型、布爾型和浮點型的option
的值
my.ini文件示例:
[client]
port = 3306
user = mysql
password = mysql
host = 127.0.0.1
[mysqld]
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
skip-external-locking
2、ConfigParser類的使用方法
(1)創建configParser對象
In [1]: import configparser
In [2]: cf = configparser.ConfigParser(allow_no_value=True)
(2)讀取配置文件內容
In [4]: cf.read('my.ini')
Out[4]: ['my.ini']
(3)獲取配置文件信息
- sections: 返回一個包含所有章節的列表
- options: 返回一個包含章節下所有選項的列表
- has_section: 判斷章節是否存在
- has_options: 判斷某個選項是否存在
- items: 以元組的形式返回所有的選項
- get、getboolean、getint、getfloat: 獲取選項的值
同時需要注意getboolean()
方法能判斷True/False的值有: ‘yes’/‘no’, ‘on’/‘off’, ‘true’/‘false’ 和 ‘1’/‘0’
In [4]: cf.sections() # 返回一個包含所有章節的列表
Out[4]: ['client','mysq1d']
In [5]: cf.has_section('client') # 判斷章節是否存在
0ut[5]: True
In [6]cf.options('client ') # 判斷某個選項是否存在
Out[6]: ['port", 'user', 'password', 'host' ]
In [7]: cf.has_option('client', 'user') # 判斷某個選項是否存在
0ut[7]: True
In [8]: cf.get('client',' port') # 獲取選項的值
0ut[8]: '3306'
In [9]: cf.getint('client','port') # 獲取選項的值
0ut[9]: 3306
(4)修改配置文件
常用方法:
- remove_section: 刪除一個章節
- add_section: 添加一個章節
- remove_option: 刪除一個選項
- set: 添加一個選項
- write: 將ConfigParser兌現中的數據保存到文件中
方法測試:
In [11]: cf.remove_section('client') # 刪除一個章節
Out[11]: True
In [14]: cf.write(open('my.ini','w')) # 將ConfigParser兌現中的數據保存到文件中
#可在PyCharm中my.ini文件查看是否少了'client‘字段。
In [15]: cf.add.section('client') # 添加一個章節
In [16]: cf.set('client','port','3306') # 添加一個選項
In [17]: cf.set('client','user','mysq1') # 添加一個選項
In [18]: cf.set('client','password' 'mysq1') # 添加一個選項
In [19]: cf.set('client','host','127.0.0.1') # 添加一個選項
In [20]: cf.write(open('my.ini','w')) # 將ConfigParser兌現中的數據保存到文件中
#可在PyCharm中my.ini文件查看是否增加了'client‘字段。
In [21]: cf.remove_option('client', 'host') # 刪除一個選項**
Out[21]: True
In [22]: cf.write(open('my.ini','w' )) # 將ConfigParser兌現中的數據保存到文件中
#可在PyCharm中my.ini文件查看是否減少了指定選項。
可在PyCharm上查看測試效果。
3、常見異常
異常 | 描述 |
---|---|
ConfigParser.Error | 所有異常的基類 |
ConfigParser.NoSectionError | 指定的section沒有找到 |
ConfigParser.DuplicateSectionError | 調用add_section() 時,section名稱已經被使用 |
ConfigParser.NoOptionError | 指定的參數沒有找到 |
ConfigParser.InterpolationError | 當執行字符串插值時出現問題時,出現異常的基類 |
ConfigParser.InterpolationDepthError | 當字符串插值無法完成時,因爲迭代次數超過了最大的範圍,所以無法完成。InterpolationError的子類 |
InterpolationMissingOptionError | 當引用的選項不存在時,會出現異常。InterpolationError的子類 |
ConfigParser.InterpolationSyntaxError | 當產生替換的源文本不符合所需的語法時,就會出現異常。InterpolationError的子類。 |
ConfigParser.MissingSectionHeaderError | 當試圖解析一個沒有分段標題的文件時,會出現異常。 |
ConfigParser.ParsingError | 當試圖解析文件時發生錯誤時,會出現異常 |
ConfigParser.MAX_INTERPOLATION_DEPTH | 當raw參數爲false時,get()的遞歸插值的最大深度。這隻適用於ConfigParser類 |
二、查找文件
PyCharm創建測試文件,格式如下:
G:\四期\python\ConfigParser\files>tree /f
卷 學習 的文件夾 PATH 列表
卷序列號爲 7C11-994A
G:.
│ a.jpg
│ A.png
│ b.jpg
│ c.png
│ e.bmp
│ f.txt
│ ff.txt
│ find_file.py
│ find_file2.py
│ find_file3.py
│
└─test
測試一下
find_file.py
import os
for item in os.listdir('.'):
if os.path.isfile(item):
print(item)
輸出結果如下:
a.jpg
A.png
b.jpg
c.png
e.bmp
f.txt
ff.txt
find_file.py
find_file2.py
find_file3.py
1、使用fnmatch找到特定文件
<1>fnmatch支持的通配符
字符 | 函數 |
---|---|
* | 匹配所有字符 |
? | 匹配單個字符 |
[seq] | 匹配指定範圍內的字符 |
[!seq] | 匹配不在指定範圍內的字符 |
<2>fnmatch的基本使用
fnmatch這個庫相對比較簡單,只有4個函數,分別是fnmatch、fnmatchcase、filter和translate,其中最常用的是fnmatch。主要功能如下:
- fnmatch:判斷文件名是否符合特定的模式。
- fnmatchcase:判斷文件名是否符合特定的模式,區分大小寫。
- filter:返回輸入列表中,符合特定模式的文件名列表。
- translate:將通配符模式轉換成正則表達式。
fnmatch和fnmatchcase用法相同,判斷名稱是否符合表達式,返回True or False
(1)fnmatch.fnmatch():一次只能處理一個文件
find_file2.py
import os
import fnmatch
for item in os.listdir('.'):
if os.path.isfile(item):
# if fnmatch.fnmatch(item,'*.jpg'):
# if fnmatch.fnmatch(item, '[a-e].*'):
# if fnmatch.fnmatch(item, '[a-z]?.txt'):
# if fnmatch.fnmatch(item, '[!a-c]*'):
print(item)
輸出結果如下:
#輸出以“.jpg”爲結尾的文件
a.jpg
b.jpg
#輸出以“a-e”爲標題的文件
a.jpg
A.png
b.jpg
c.png
e.bmp
#輸出以“a-z”和一個任意字符爲標題,並且以“.txt”爲後綴的文件
ff.txt
#輸出除了以“a-c”爲開通的文件
e.bmp
f.txt
ff.txt
find_file.py
find_file2.py
find_file3.py
(2)fnmath.filter():一次可以處理多個文件
find_file3.py
import os
import fnmatch
items = os.listdir('.')
files = fnmatch.filter(items, '[a-c]*')
print(files)
輸出結果如下:
['a.jpg', 'A.png', 'b.jpg', 'c.png']
2、使用glob找到特定文件
glob模塊支持的通配符:
通配符 | 功能 |
---|---|
* | 匹配0或多個字符 |
** | 匹配所有文件、目錄、子目錄和子目錄裏的文件(3.5版本新增) |
? | 匹配1個字符,與正則表達式裏的?不同 |
[exp] | 匹配指定範圍內的字符,如:[1-9]匹配1至9範圍內的字符 |
[!exp] | 匹配不在指定範圍內的字符 |
標準庫glob的作用相當於os.listdir()加上fnmatch。使用glob以後,不需要調用os.listdir獲取文件列表,直接通過模式匹配即可。如下所示:
import glob
file = glob.glob('*.txt')
print(file)
輸出結果如下:
['f.txt', 'ff.txt']
glob基本使用
glob和iglob的區別在於glob返回的是一個列表,iglob返回的是一個生成器對象
>>> import glob
>>> glob.glob('*.txt')
['a1.txt', 'a2.txt', 'aA.txt']
>>> g = glob.iglob('*.txt') # 使用iglob返回的是一個生成器
>>> g
<generator object _iglob at 0x1050bbba0>
>>> list(g)
['a1.txt', 'a2.txt', 'aA.txt']
>>>
PS:glob同樣支持通配符和fnmatch相同,這裏不在列舉,並且在通配符表達式中支持路徑
>>> glob.glob('/Users/DahlHin/github/test/*.txt')
['/Users/DahlHin/github/test/a1.txt','/Users/DahlHin/github/test/a2.txt','/Users/DahlHin/github/test/aA.txt']
總結:雖然glob模塊可以很輕鬆地匹配特定文件和文件夾,但是僅僅支持少量的通配符,沒辦法像正則表達式一樣匹配更復雜的字符串。使用的時候應當認真考慮使用場景,根據需求針對性地選擇解決方案。