網(wǎng)絡(luò)工程師Python數(shù)據(jù)存儲(chǔ)(第1節(jié),CSV文件)
網(wǎng)絡(luò)自動(dòng)化運(yùn)維演進(jìn)的一個(gè)方向大致過(guò)程:網(wǎng)絡(luò)工程師從關(guān)注配置制作腳本,完成后上設(shè)備刷配置,慢慢地演化為網(wǎng)絡(luò)工程師關(guān)注和確定設(shè)備配置的某些重要控制參數(shù),而把制作腳本任務(wù)交給Jinja2等去渲染生成,把下發(fā)腳本工作交由nornir等去完成。也就是說(shuō),網(wǎng)工從設(shè)備運(yùn)維有轉(zhuǎn)向數(shù)據(jù)運(yùn)維的前景。
當(dāng)然,演進(jìn)過(guò)程溯洄從之,道阻且躋,溯游從之,宛若從入門到放棄。我覺得只能不緊急的時(shí)候多做點(diǎn)重要的事情,才能慢慢積累沉淀,沿途拾起幾塊屬于自己的自動(dòng)化碎片~發(fā)現(xiàn)那早已是遺落的感傷,于是揮揮衣袖,繼續(xù)趕路~。
那么,數(shù)據(jù)運(yùn)維中的數(shù)據(jù)存在哪,以什么形式存,怎么存放,怎么取用?接下來(lái)我將梳理一點(diǎn)關(guān)于Python數(shù)據(jù)存儲(chǔ)的內(nèi)容。這篇我們先來(lái)促促CSV文件。
〇、參考說(shuō)明
文章出自:網(wǎng)絡(luò)工程師Python數(shù)據(jù)存儲(chǔ)(第1節(jié),CSV文件)
如果你不知道從何讀起,建議從這篇《目錄》開始,連接如下:
【網(wǎng)工手藝】專欄入口(總目錄 | 我全開源寫作 | 你別買盜版書)
本文部分參考書籍《Python for network engineers》,純英文,推薦移步閱讀。
本文長(zhǎng)期維護(hù),歡迎參與勘誤(包括知識(shí)點(diǎn),錯(cuò)別字,文字表述)。
如有侵權(quán)行為,可私信刪除
一、背景簡(jiǎn)介
一名網(wǎng)絡(luò)工程師出差,能一直在機(jī)房或網(wǎng)管后臺(tái)嗎?當(dāng)然不能,還得住酒店歇息啊。同理,Python處理的數(shù)據(jù),總不能老待在程序內(nèi)存中,最終得存儲(chǔ)放置進(jìn)硬盤的!那么以什么形式存放進(jìn)硬盤呢?多數(shù)是結(jié)構(gòu)化數(shù)據(jù),如Python中的pickle(泡菜雜壇子)類、CSV、JSON、YAML形式,當(dāng)然還有強(qiáng)大的數(shù)據(jù)庫(kù)系統(tǒng)。
鑒于pickle是Pyhon特有內(nèi)置形式,目前較少與其它系統(tǒng)直接對(duì)接;數(shù)據(jù)庫(kù)系統(tǒng)又稍龐大,可能能單開一個(gè)系列來(lái)梳理。所以,這系列我們先聚焦CSV、JSON、YAML形式吧。
此次,我們先重點(diǎn)關(guān)注CSV吧。CSV說(shuō)白了就是一種結(jié)構(gòu)化的表格。表格大家都很熟悉了,如excel一打開就是一個(gè)表。結(jié)構(gòu)化呢?簡(jiǎn)單理解就是,打開的excel表格您千萬(wàn)不要這里合并一下單元格,合并單元格操作,會(huì)破壞表的結(jié)構(gòu),它就失去結(jié)構(gòu)化了。當(dāng)然,我這么表述可能不嚴(yán)謹(jǐn),關(guān)鍵是讓你能有熱乎乎的感受。
CSV (comma-separated value),顧名思義,逗號(hào)隔開的數(shù)據(jù)。這種數(shù)據(jù)從表格中獲取,也可以從數(shù)據(jù)庫(kù)中獲取,可以用excel打開,還可以導(dǎo)入數(shù)據(jù)庫(kù)。沒錯(cuò),它就是一種信息存儲(chǔ)媒介。
二、CSV操作
2.1 初識(shí)CSV
在這種格式中,CSV文件中的一行,即是表格的一行。盡管它名字叫做“逗號(hào)分割數(shù)據(jù)”,但除了用逗號(hào)分割外,其實(shí)還可以使用其它的符號(hào)進(jìn)行分割。使用不同符號(hào)分割的文件,文件名可能稍有不同,比如TSV
(用制表符分割)。盡管如此,通常情況下,我們還是習(xí)慣性把他們都統(tǒng)稱為“CSV”。
hostname,vendor,model,location
sw1,Huawei,5700,Beijing
sw2,Huawei,3700,Shanghai
sw3,Huawei,9300,Guangzhou
sw4,Huawei,9306,Shenzhen
sw5,Huawei,12800,Hangzhou
在Python的標(biāo)準(zhǔn)庫(kù)中,有一個(gè)專門處理CSV文件的模塊。題外話,啥叫“Python標(biāo)準(zhǔn)庫(kù)”,就是您安裝好Python后,無(wú)需再pip安裝,就能直接import
的那些庫(kù)。
2.2 讀取CSV
相對(duì)于其它IDE,我更傾向于用IDLE演示,因?yàn)橹灰惭bPython了它就存在了,不用其它一些聯(lián)調(diào)操作。此外,我還覺得它在很大程度上已經(jīng)能滿足網(wǎng)工Python行當(dāng)里很多日常小應(yīng)用了。
來(lái),我們打開IDLE來(lái)敲指令。
使用下面這種形式的代碼塊。我可以有效防止你“偷懶”,直接把代碼全部復(fù)制過(guò)去一run,以為自己就懂了。
這樣的代碼塊,你只能自己手敲,至少只能一行一行復(fù)制。你只有自己敲起來(lái),進(jìn)而才能更好感受Python縮進(jìn)等語(yǔ)法結(jié)構(gòu),從而真正入門。
你看我何等用心良苦,趕緊一起來(lái)敲吧。
>>> import csv
>>> csv_path = r'E:\***\csv-lab1.csv' #文件路徑,可根據(jù)自己實(shí)際情況。
>>> with open(csv_path) as f:
reader = csv.reader(f)
for row in reader:
print(row)
['hostname', 'vendor', 'model', 'location']
['sw1', 'Huawei', '5700', 'Beijing']
['sw2', 'Huawei', '3700', 'Shanghai']
['sw3', 'Huawei', '9300', 'Guangzhou']
['sw4', 'Huawei', '9306', 'Shenzhen']
['sw5', 'Huawei', '12800', 'Hangzhou']
>>>
注意,csv.reader
返回的是一個(gè)迭代器(iterator)。
>>> with open(csv_path) as f:
reader = csv.reader(f)
print(reader)
<_csv.reader object at 0x0000017F1B24CBA8>
>>>
如有需要,可以用list
函數(shù)將這個(gè)迭代器處理成列表。
>>> with open(csv_path) as f:
reader = csv.reader(f)
print(list(reader))
[['hostname', 'vendor', 'model', 'location'], ['sw1', 'Huawei', '5700', 'Beijing'], ['sw2', 'Huawei', '3700', 'Shanghai'], ['sw3', 'Huawei', '9300', 'Guangzhou'], ['sw4', 'Huawei', '9306', 'Shenzhen'], ['sw5', 'Huawei', '12800', 'Hangzhou']]
>>>
通常情況下,表頭需單獨(dú)使用,可以特殊處理一下。
>>> with open(csv_path) as f:
reader = csv.reader(f)
headers = next(reader)
print('Headers: ',headers)
for row in reader:
print(row)
Headers: ['hostname', 'vendor', 'model', 'location']
['sw1', 'Huawei', '5700', 'Beijing']
['sw2', 'Huawei', '3700', 'Shanghai']
['sw3', 'Huawei', '9300', 'Guangzhou']
['sw4', 'Huawei', '9306', 'Shenzhen']
['sw5', 'Huawei', '12800', 'Hangzhou']
>>>
有時(shí)候,我們還需要表頭信息與每一行的數(shù)據(jù)相結(jié)合,那此時(shí)可以用上字典數(shù)據(jù)類型。
>>> with open(csv_path) as f:
reader = csv.DictReader(f)
for row in reader:
# print(row)
print(row['hostname'],row['model'])
sw1 5700
sw2 3700
sw3 9300
sw4 9306
sw5 12800
為了簡(jiǎn)潔一點(diǎn),print(row)
代碼行,被我注釋了。如若你有興趣,可去掉注釋行再運(yùn)行試試。
2.3 寫入CSV(writerow)
我們已體驗(yàn)了CSV的讀取操作,并不難吧?那CSV的寫入操作如何呢?我們馬上來(lái)嘗試一下。
>>> import csv
>>> data = [['hostname','vendor','model','location'],
['sw1','Huawei','5700','Beijing'],
['sw2','Huawei','3700','Shanghai'],
['sw3','Huawei','9300','Guangzhou'],
['sw4','Huawei','9306','Shenzhen'],
['sw5','Huawei','12800','Hangzhou']]
>>> csv_path = r'E:\……\csv-lab1-writing.csv' #存放文件路徑,可根據(jù)自己實(shí)際情況。
>>> with open(csv_path,'w',newline='') as f:
writer = csv.writer(f)
for row in data:
writer.writerow(row)
回車后,后面會(huì)有一些雜雜的返回,屬于干擾項(xiàng)無(wú)需理會(huì),我們關(guān)注的是生成CSV文件。
注意幾點(diǎn):
- 參數(shù)
w
,表示寫入,不加則默認(rèn)是讀r
。 -
newline=''
,不加這個(gè)參數(shù)的話,結(jié)果會(huì)有冗余的空行,可以嘗試一下。 - 如果有中文等,可能還要留意編解碼問題,否則容易出現(xiàn)亂碼。
文件生成之后,回過(guò)頭來(lái),我們同樣可以用Python腳本來(lái)讀取。
>>> with open(csv_path) as f:
print(f.read())
hostname,vendor,model,location
sw1,Huawei,5700,Beijing
sw2,Huawei,3700,Shanghai
sw3,Huawei,9300,Guangzhou
sw4,Huawei,9306,Shenzhen
sw5,Huawei,12800,Hangzhou
2.4 寫入CSV(文本帶逗號(hào))
>>> import csv
>>> data = [['hostname','vendor','model','location'],
['sw1','Huawei','5700','Beijing,Xicheng'],
['sw2','Huawei','3700','Shanghai'],
['sw3','Huawei','9300','Guangzhou,Tianhe'],
['sw4','Huawei','9306','Shenzhen'],
['sw5','Huawei','12800','Hangzhou']]
>>> csv_path = r'E:\……\csv-lab1-writing.csv' #存放文件路徑,可根據(jù)自己實(shí)際情況。
>>> with open(csv_path,'w',newline='') as f:
writer = csv.writer(f)
for row in data:
writer.writerow(row)
現(xiàn)在我們把'Beijing'
改成了'Beijing,Xicheng'
,把'Guangzhou'
改成了'Guangzhou,Tianhe'
。請(qǐng)注意觀察交互執(zhí)行結(jié)果。
有意思吧?'Beijing,Xicheng'
和'Guangzhou,Tianhe'
這兩處print
時(shí),自動(dòng)戴上了“小耳朵”。
這是因?yàn)椋址斜旧碛卸禾?hào),為了避免歧義,被當(dāng)做分割符,所以csv模塊自動(dòng)做了特殊處理。
干脆,全部都戴上“小耳朵”吧,參數(shù)quoting=csv.QUOTE_NONNUMERIC
來(lái)幫忙。
>>> with open(csv_path,'w',newline='') as f:
writer = csv.writer(f,quoting=csv.QUOTE_NONNUMERIC)
for row in data:
writer.writerow(row)
40
41
34
42
34
35
>>>
>>>
>>> with open(csv_path) as f:
print(f.read())
"hostname","vendor","model","location"
"sw1","Huawei","5700","Beijing,Xicheng"
"sw2","Huawei","3700","Shanghai"
"sw3","Huawei","9300","Guangzhou,Tianhe"
"sw4","Huawei","9306","Shenzhen"
"sw5","Huawei","12800","Hangzhou"
>>>
只要是字符串類型的,通通被括起來(lái)。
2.5 寫入CSV(writerows)
除方法writerow外,我們還可以用方法writerows。我們調(diào)整一下原先的例子。
>>> import csv
>>> data = [['hostname','vendor','model','location'],
['sw1','Huawei','5700','Beijing,Xicheng'],
['sw2','Huawei','3700','Shanghai'],
['sw3','Huawei','9300','Guangzhou,Tianhe'],
['sw4','Huawei','9306','Shenzhen'],
['sw5','Huawei','12800','Hangzhou']]
>>> csv_path = r'E:\……\csv-lab1-writing.csv' #存放文件路徑,可根據(jù)自己實(shí)際情況。
>>> with open(csv_path,'w',newline='') as f:
writer = csv.writer(f,quoting=csv.QUOTE_NONNUMERIC)
writer.writerows(data)
>>> with open(csv_path) as f:
print(f.read())
"hostname","vendor","model","location"
"sw1","Huawei","5700","Beijing,Xicheng"
"sw2","Huawei","3700","Shanghai"
"sw3","Huawei","9300","Guangzhou,Tianhe"
"sw4","Huawei","9306","Shenzhen"
"sw5","Huawei","12800","Hangzhou"
>>>
腳本正常執(zhí)行后,在實(shí)驗(yàn)文件夾中,會(huì)重新生成文件。截圖略。
看起來(lái)會(huì)不會(huì)簡(jiǎn)潔很多呢?證明writerows
更好嗎?Nonono,這些都是工具。工具并沒有好壞之分。小刀大炮各有厲害之處,需要要適配具體的使用場(chǎng)景。
2.6 寫入CSV(DictWriter)
我們還可以使用方法DictWriter
,把字典類型的數(shù)據(jù),直接寫入到CSV文件。
DictWriter
操作起來(lái)與writer
類似, 但是,字典類型是無(wú)序的(確切地說(shuō),Python3.6
之后字典類型就是有序的,但在我的應(yīng)用范圍內(nèi),我一直把它當(dāng)成無(wú)序的來(lái)理解)。所以,我們又得引入一個(gè)參數(shù)fieldnames
,來(lái)標(biāo)識(shí)順序。
>>> import csv
>>> data = [{
'hostname': 'sw1',
'location': 'Beijing,Xicheng',
'model': '5700',
'vendor': 'Huawei'
}, {
'hostname': 'sw2',
'location': 'Shanghai',
'model': '3700',
'vendor': 'Huawei'
}, {
'hostname': 'sw3',
'location': 'Guangzhou,Tianhe',
'model': '9300',
'vendor': 'Huawei'
}, {
'hostname': 'sw4',
'location': 'Shenzhen',
'model': '9306',
'vendor': 'Huawei'
}, {
'hostname': 'sw5',
'location': 'Hangzhou',
'model': '12800',
'vendor': 'Huawei'
}]
>>>
>>> csv_path = r'E:\……\csv-lab1-writing.csv' #存放文件路徑,可根據(jù)自己實(shí)際情況。
>>>
>>> with open(csv_path,'w',newline='') as f:
writer = csv.DictWriter(
f, fieldnames=list(data[0].keys()),quoting=csv.QUOTE_NONNUMERIC)
writer.writeheader()
for d in data:
writer.writerow(d)
41
34
42
34
35
>>> with open(csv_path) as f:
print(f.read())
"hostname","location","model","vendor"
"sw1","Beijing,Xicheng","5700","Huawei"
"sw2","Shanghai","3700","Huawei"
"sw3","Guangzhou,Tianhe","9300","Huawei"
"sw4","Shenzhen","9306","Huawei"
"sw5","Hangzhou","12800","Huawei"
>>>
這種看起來(lái)稍微有點(diǎn)繞,我們要把我一點(diǎn),fieldnames
是來(lái)控制表頭的順序的,比如第一項(xiàng)是hostname
,最后一項(xiàng)是vendor
。
2.7 自定義分割符(dictwriter)
我前面已提及TSV
,分割符自然可以是其它的。
此時(shí),需要參數(shù)delimiter
來(lái)幫忙。
>>> import csv
>>> csv_path = r'E:\***\csv-lab1.csv' #文件路徑,可根據(jù)自己實(shí)際情況。
>>> with open(csv_path) as f:
reader = csv.reader(f)
for row in reader:
print(row)
['hostname:vendor:model:location']
['sw1:Huawei:5700:Beijing']
['sw2:Huawei:3700:Shanghai']
['sw3:Huawei:9300:Guangzhou']
['sw4:Huawei:9306:Shenzhen']
['sw5:Huawei:12800:Hangzhou']
>>>
>>>
>>> with open(csv_path) as f:
reader = csv.reader(f, delimiter=':')
for row in reader:
print(row)
['hostname', 'vendor', 'model', 'location']
['sw1', 'Huawei', '5700', 'Beijing']
['sw2', 'Huawei', '3700', 'Shanghai']
['sw3', 'Huawei', '9300', 'Guangzhou']
['sw4', 'Huawei', '9306', 'Shenzhen']
['sw5', 'Huawei', '12800', 'Hangzhou']
>>>
本實(shí)驗(yàn),我們用冒號(hào)做分隔符,因而需指定參數(shù)delimiter
;如若不指定,默認(rèn)分割符為逗號(hào)。
三、本文總結(jié)
CSV
在運(yùn)維各種應(yīng)用系統(tǒng)中,常被作為數(shù)據(jù)導(dǎo)出導(dǎo)入的媒介,比如告警信息,資源表,日志等。
Python的csv模塊相當(dāng)于一個(gè)API,讓我們可以通過(guò)腳本,調(diào)取到存放在硬盤中CSV文件里的數(shù)據(jù),隨后將其放入內(nèi)存,進(jìn)行數(shù)據(jù)處理,加工。數(shù)據(jù)處理之后,如果你暫時(shí)不知道要用什么形式進(jìn)行存儲(chǔ),那就還用CSV吧。
網(wǎng)絡(luò)工程師的Python之路:網(wǎng)絡(luò)運(yùn)維自動(dòng)化實(shí)戰(zhàn)(第2版
京東
¥93.60
去購(gòu)買
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-768043.html
我讀過(guò)的書、用過(guò)的物(持續(xù)更新)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-768043.html
到了這里,關(guān)于Python操作寫入/讀取csv文件的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!