淺談python之利用pandas和openpyxl讀取excel數據


在學接口自動化測試時, 需要從excel中讀取測試用例的數據, 假如我的數據是這樣的:

最好是每行數據對應着一條測試用例, 為方便取值, 我選擇使用pandas庫, 先安裝 pip install pandas.

然后導入:

1 import pandas as pd
2 df=pd.read_excel('../test_data/test_data.xlsx',sheet_name='hehe')

默認第一行數據是表頭,先來簡單了解一下pandas的用法:

輸入:

1 print(df.head())  # 矩陣式輸出,無法利用數據,忽略
2 print(df.ix[0])    # 索引從第二行開始,0表示表中的第二行,表頭與行數據成映射關系

輸出:

學號 姓名 年齡 攻擊力
0 1 李連傑 27 96
1 2 甄子丹 27 93
2 3 成龍 36 90
3 4 洪金寶 38 89
4 5 吳京 16 91


學號 1
姓名 李連傑
年齡 27
攻擊力 96

輸入:

1 print(df.ix[0,1])  #  第二行第二個數據,B2
2 print(df.ix[1].values)    # 第3行數據
3 print(df.ix[[1,2]].values)    # 第3,4行數據,注意輸出多行里面應該要嵌套列表

輸出:

李連傑

[2 '甄子丹' 27 93]

[ [2 '甄子丹' 27 93]
[3 '成龍' 36 90] ]

輸入:

print(df.ix[[1,2],['年齡']].values)  #3,4行里輸出表頭為'年齡'的列的數據,嵌套列表
print(df.ix[:,['攻擊力']].values)    # 輸出所有行的表頭為'攻擊力'的列的數據,即D2-D9,嵌套列表
print(df.ix[:].values)     # 輸出所有行
print(df.values)           # 輸出所有行,結果與上一樣

輸出:

[[27]
[36]]


[[ 96]
[ 93]
[ 90]
[ 89]
[ 91]
[100]
[ 92]
[ 1]]


[[1 '李連傑' 27 96]
[2 '甄子丹' 27 93]
[3 '成龍' 36 90]
[4 '洪金寶' 38 89]
[5 '吳京' 16 91]
[6 '李小龍' 50 100]
[7 '趙文卓' 18 92]
[8 '劉亦菲' 3 1]]

輸入:

1 print(df.index.values)     # 輸出行號 
2 print(df.columns.values)      # 輸出所有列標題
3 print(df['年齡'].values)        #輸出指定標題列的數據
4 print(df.sample(3).values)    #隨機輸出三行數據

輸出:

[0 1 2 3 4 5 6 7]

['學號' '姓名' '年齡' '攻擊力']

[27 27 36 38 16 50 18 3]

[[3 '成龍' 36 90]
[6 '李小龍' 50 100]
[7 '趙文卓' 18 92]]

輸入:

1 print(df.ix[1,['學號','年齡']].to_dict()) # 字典的形式輸出第三行特定列

 輸出:

{'學號': 2, '年齡': 27}

有表頭的情況下, 輸出的數據若有多個元素,都是<class 'numpy.ndarray'>的類型的,即[[] [] [] []],大列表嵌套多個小列表,小列表之間沒有逗號隔開, 輸出的數據若只有一個元素,那就是str或者int.

 然而, 在自動化測試中我們需要的可能是這樣的數據:

[{'學號': 1, '姓名': '李連傑', '年齡': 27, '攻擊力': 96}, {'學號': 2, '姓名': '甄子丹', '年齡': 27, '攻擊力': 93}]

即大列表嵌套多字典, 每條字典就是一個測試用例的數據, 那么怎么取出這種類型的呢?

1 df=pd.read_excel('../test_data/test_data.xlsx') #默認第一個sheet
2 test_data=[]
3 for i in df.index.values:#獲取行號的索引,並對其進行遍歷:
4     #根據i來獲取每一行指定的數據 並利用to_dict轉成字典
5     row_data=df.ix[i,['學號','姓名','年齡','攻擊力']].to_dict()
6     test_data.append(row_data)
7 print("最終獲取到的數據是:{0}".format(test_data))

 輸出:

最終獲取到的數據是:[{'學號': 1, '姓名': '李連傑', '年齡': 27, '攻擊力': 96}, 
          {'學號': 2, '姓名': '甄子丹', '年齡': 27, '攻擊力': 93},
          {'學號': 3, '姓名': '成龍', '年齡': 36, '攻擊力': 90},
          {'學號': 4, '姓名': '洪金寶', '年齡': 38, '攻擊力': 89},
          {'學號': 5, '姓名': '吳京', '年齡': 16, '攻擊力': 91},
          {'學號': 6, '姓名': '李小龍', '年齡': 50, '攻擊力': 100},
          {'學號': 7, '姓名': '趙文卓', '年齡': 18, '攻擊力': 92},
          {'學號': 8, '姓名': '劉亦菲', '年齡': 3, '攻擊力': 1}]

怎么樣,大功告成了吧, 然而你會說, 好麻煩呀,有簡單點的方法嗎?哈哈,有!

我們來看to_dict方法:

作用是把數據格式轉換成字典型的,兩個參數,into不管它,前面orient有很多值,我先輸出幾個看看:

1 import pandas as pd
2 p=pd.read_excel('../test_data/test_data.xlsx')
3 
4 print("orient='list'-->",p.to_dict(orient='list')) # <class 'dict'>將表頭作為key,將每列的值放在列表中,將列表作為value
5 print("orient='index'-->:",p.to_dict(orient='index')) # 將行的索引值作為key,將存放數據的字典作為value
6 print("orient='records'-->",p.to_dict(orient='records')) # 大列表嵌套多字典,適合測試用例
7 print(p.to_dict(orient='dict'))
8 print(p.to_dict(orient='split'))

 

結果:

1 orient='list'--> {'學號': [1, 2, 3, 4, 5, 6, 7, 8], '姓名': ['李連傑', '甄子丹', '成龍', '洪金寶', '吳京', '李小龍', '趙文卓', '劉亦菲'], '年齡': [27, 27, 36, 38, 16, 50, 18, 3], '攻擊力': [96, 93, 90, 89, 91, 100, 92, 1]}
2 orient='index'-->: {0: {'學號': 1, '姓名': '李連傑', '年齡': 27, '攻擊力': 96}, 1: {'學號': 2, '姓名': '甄子丹', '年齡': 27, '攻擊力': 93}, 2: {'學號': 3, '姓名': '成龍', '年齡': 36, '攻擊力': 90}, 3: {'學號': 4, '姓名': '洪金寶', '年齡': 38, '攻擊力': 89}, 4: {'學號': 5, '姓名': '吳京', '年齡': 16, '攻擊力': 91}, 5: {'學號': 6, '姓名': '李小龍', '年齡': 50, '攻擊力': 100}, 6: {'學號': 7, '姓名': '趙文卓', '年齡': 18, '攻擊力': 92}, 7: {'學號': 8, '姓名': '劉亦菲', '年齡': 3, '攻擊力': 1}}
3 orient='records'--> [{'學號': 1, '姓名': '李連傑', '年齡': 27, '攻擊力': 96}, {'學號': 2, '姓名': '甄子丹', '年齡': 27, '攻擊力': 93}, {'學號': 3, '姓名': '成龍', '年齡': 36, '攻擊力': 90}, {'學號': 4, '姓名': '洪金寶', '年齡': 38, '攻擊力': 89}, {'學號': 5, '姓名': '吳京', '年齡': 16, '攻擊力': 91}, {'學號': 6, '姓名': '李小龍', '年齡': 50, '攻擊力': 100}, {'學號': 7, '姓名': '趙文卓', '年齡': 18, '攻擊力': 92}, {'學號': 8, '姓名': '劉亦菲', '年齡': 3, '攻擊力': 1}]
4 {'學號': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8}, '姓名': {0: '李連傑', 1: '甄子丹', 2: '成龍', 3: '洪金寶', 4: '吳京', 5: '李小龍', 6: '趙文卓', 7: '劉亦菲'}, '年齡': {0: 27, 1: 27, 2: 36, 3: 38, 4: 16, 5: 50, 6: 18, 7: 3}, '攻擊力': {0: 96, 1: 93, 2: 90, 3: 89, 4: 91, 5: 100, 6: 92, 7: 1}}
5 {'index': [0, 1, 2, 3, 4, 5, 6, 7], 'columns': ['學號', '姓名', '年齡', '攻擊力'], 'data': [[1, '李連傑', 27, 96], [2, '甄子丹', 27, 93], [3, '成龍', 36, 90], [4, '洪金寶', 38, 89], [5, '吳京', 16, 91], [6, '李小龍', 50, 100], [7, '趙文卓', 18, 92], [8, '劉亦菲', 3, 1]]}

 

 

發現我們測試需要的數據格式也在其中, 那就是orient='records', 所以兩行代碼解決了從excel中取出測試數據的事情, 好開心!

1 p=pd.read_excel('../test_data/test_data.xlsx')
2 print(p.to_dict(orient='records'))

 



取出數據測試完畢后想寫回測試結果該怎么辦呢,這就要談談另一個模塊了:openpyxl

這里我把讀取數據寫成一個類, 利用openpyxl也可以拿出大列表嵌套多字典的數據類型, 但稍微麻煩了點, 不過它還可以寫回數據. 如下:

 1 from openpyxl import load_workbook
 2 from tools.read_config import ReadConfig
 3 
 4 class ReadExcel:
 5     button = ReadConfig().read_config('case.config','MOD','button')
 6     def read_excel_openpyxl(self,file_name,sheet_name):
 7         '''從excel讀取數據並以大列表嵌套多字典的形式輸出'''
 8         wb=load_workbook(file_name)
 9         sheet=wb[sheet_name]
10         tit = []
11         test_data = []
12         row = sheet.max_row + 1
13         column = sheet.max_column + 1
14         for i in range(1, row):
15             ele = {}
16             for j in range(1, column):
17                 if i == 1:
18                     res = sheet.cell(i, j).value
19                     tit.append(res)
20                 else:
21                     ele[tit[j - 1]] = sheet.cell(i, j).value
22             test_data.append(ele)  # 此時的test_data里面第一個是空列表
23 
24         test_data_new = []
25         for item in test_data:
26             if item != {}:  # 去除空列表
27                 test_data_new.append(item)
28         return self.get_which_row(test_data_new)
29 
30     def write_back_unittest(self,file_name,sheet_name,value,row,cloumn):
31         '''unittest框架用這個'''
32         wb=load_workbook(file_name)
33         sheet=wb[sheet_name]
34         sheet.cell(row,cloumn).value=value
35         wb.save(file_name)
36 
37     def get_which_row(self,test_data_new):
38         '''根據button值決定取出哪些行的數據作為測試用例'''
39         test_data_final=[]
40         if self.button == 'all':
41             return test_data_new
42         else:
43             for i in eval(self.button):  # 配置文件里button的值是字符串類型,切記!!!
44                 test_data_final.append(test_data_new[i-1])
45             return test_data_final

 

 END


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM