python自动化测试之如何解析excel文件
前言
自动化测试中我们存放数据无非是使用文件或者数据库,那么文件可以是csv,xlsx,xml,甚至是txt文件,通常excel文件往往是我们的首选,无论是编写测试用例还是存放测试数据,excel都是很方便的。那么今天我们就把不同模块处理excel文件的方法做个总结,直接做封装,方便我们以后直接使用,增加工作效率。
openpyxl
openpyxl是个第三方库,首先我们使用命令pipinstallopenpyxl直接安装
注:openpyxl操作excel时,行号和列号都是从1开始计算的
封装代码
"""
------------------------------------
@Time:2019/5/1318:00
@Auth:linux超
@File:ParseExcel.py
@IDE:PyCharm
@Motto:Realwarriors,daretofacethebleakwarning,daretofacetheincisiveerror!
------------------------------------
"""
fromopenpyxlimportload_workbook
fromopenpyxl.stylesimportFont
fromopenpyxl.styles.colorsimportBLACK
fromcollectionsimportnamedtuple
classParseExcel(object):
"""解析excel文件"""
def__init__(self,filename,sheet_name=None):
try:
self.filename=filename
self.sheet_name=sheet_name
self.wb=load_workbook(self.filename)
ifself.sheet_nameisNone:
self.work_sheet=self.wb.active
else:
self.work_sheet=self.wb[self.sheet_name]
exceptFileNotFoundErrorase:
raisee
defget_max_row_num(self):
"""获取最大行号"""
max_row_num=self.work_sheet.max_row
returnmax_row_num
defget_max_column_num(self):
"""获取最大列号"""
max_column=self.work_sheet.max_column
returnmax_column
defget_cell_value(self,coordinate=None,row=None,column=None):
"""获取指定单元格的数据"""
ifcoordinateisnotNone:
try:
returnself.work_sheet[coordinate].value
exceptExceptionase:
raisee
elifcoordinateisNoneandrowisnotNoneandcolumnisnotNone:
ifisinstance(row,int)andisinstance(column,int):
returnself.work_sheet.cell(row=row,column=column).value
else:
raiseTypeError('rowandcolumnmustbetypeint')
else:
raiseException("InsufficientCoordinateofcell!")
defget_row_value(self,row):
"""获取某一行的数据"""
column_num=self.get_max_column_num()
row_value=[]
ifisinstance(row,int):
forcolumninrange(1,column_num+1):
values_row=self.work_sheet.cell(row,column).value
row_value.append(values_row)
returnrow_value
else:
raiseTypeError('rowmustbetypeint')
defget_column_value(self,column):
"""获取某一列数据"""
row_num=self.get_max_column_num()
column_value=[]
ifisinstance(column,int):
forrowinrange(1,row_num+1):
values_column=self.work_sheet.cell(row,column).value
column_value.append(values_column)
returncolumn_value
else:
raiseTypeError('columnmustbetypeint')
defget_all_value_1(self):
"""获取指定表单的所有数据(除去表头)"""
max_row_num=self.get_max_row_num()
max_column=self.get_max_column_num()
values=[]
forrowinrange(2,max_row_num+1):
value_list=[]
forcolumninrange(1,max_column+1):
value=self.work_sheet.cell(row,column).value
value_list.append(value)
values.append(value_list)
returnvalues
defget_all_value_2(self):
"""获取指定表单的所有数据(除去表头)"""
rows_obj=self.work_sheet.iter_rows(min_row=2,max_row=self.work_sheet.max_row,
values_only=True)#指定values_only会直接提取数据不需要再使用cell().value
values=[]
forrow_tupleinrows_obj:
value_list=[]
forvalueinrow_tuple:
value_list.append(value)
values.append(value_list)
returnvalues
defget_excel_title(self):
"""获取sheet表头"""
title_key=tuple(self.work_sheet.iter_rows(max_row=1,values_only=True))[0]
returntitle_key
defget_listdict_all_value(self):
"""获取所有数据,返回嵌套字典的列表"""
sheet_title=self.get_excel_title()
all_values=self.get_all_value_2()
value_list=[]
forvalueinall_values:
value_list.append(dict(zip(sheet_title,value)))
returnvalue_list
defget_list_nametuple_all_value(self):
"""获取所有数据,返回嵌套命名元组的列表"""
sheet_title=self.get_excel_title()
values=self.get_all_value_2()
excel=namedtuple('excel',sheet_title)
value_list=[]
forvalueinvalues:
e=excel(*value)
value_list.append(e)
returnvalue_list
defwrite_cell(self,row,column,value=None,bold=True,color=BLACK):
"""
指定单元格写入数据
:paramwork_sheet:
:paramrow:行号
:paramcolumn:列号
:paramvalue:待写入数据
:parambold:加粗,默认加粗
:paramcolor:字体颜色,默认黑色
:return:
"""
try:
ifisinstance(row,int)andisinstance(column,int):
cell_obj=self.work_sheet.cell(row,column)
cell_obj.font=Font(color=color,bold=bold)
cell_obj.value=value
self.wb.save(self.filename)
else:
raiseTypeError('rowandcolumnmustbetypeint')
exceptExceptionase:
raisee
if__name__=='__main__':
pe=ParseExcel('testdata.xlsx')
#sheet=pe.get_sheet_object('testcase')
column_row=pe.get_max_column_num()
print('最大列号:',column_row)
max_row=pe.get_max_row_num()
print('最大行号:',max_row)
#
cell_value_1=pe.get_cell_value(row=2,column=3)
print('第%d行,第%d列的数据为:%s'%(2,3,cell_value_1))
cell_value_2=pe.get_cell_value(coordinate='A5')
print('A5单元格的数据为:{}'.format(cell_value_2))
value_row=pe.get_row_value(3)
print('第{}行的数据为:{}'.format(3,value_row))
value_column=pe.get_column_value(2)
print('第{}列的数据为:{}'.format(2,value_column))
#
values_1=pe.get_all_value_1()
print('第一种方式获取所有数据\n',values_1)
values_2=pe.get_all_value_2()
print('第二种方式获取所有数据\n',values_2)
title=pe.get_excel_title()
print('表头为\n{}'.format(title))
dict_value=pe.get_listdict_all_value()
print('所有数据组成的嵌套字典的列表:\n',dict_value)
#
namedtuple_value=pe.get_list_nametuple_all_value()
print('所有数据组成的嵌套命名元组的列表:\n',namedtuple_value)
pe.write_cell(1,2,'Tc_title')
#addbylinux超at2019/05/2215:58
上面这个封装如如果用来同时操作同一个excel文件的两个sheet写入数据时,会有点小bug(写完后你会发现两个表单有一个是没有数据的)
其实原因很简单:不同对象拥有自己独立的属性,当你写操作的时候其实每个对象只针对自己的表单做了保存,所以最后一个对象写完数据后,只保存了自己的表单,其他的对象的表单实际是没有保存的。针对这个问题,对上面封装的代码进行了轻微改动
"""
------------------------------------
@Time:2019/5/229:11
@Auth:linux超
@File:ParseExcel.py
@IDE:PyCharm
@Motto:Realwarriors,daretofacethebleakwarning,daretofacetheincisiveerror!
------------------------------------
"""
fromopenpyxlimportload_workbook
fromopenpyxl.stylesimportFont
fromopenpyxl.styles.colorsimportBLACK
fromcollectionsimportnamedtuple
classParseExcel(object):
"""解析excel文件"""
def__init__(self,filename):
try:
self.filename=filename
self.__wb=load_workbook(self.filename)
exceptFileNotFoundErrorase:
raisee
defget_max_row_num(self,sheet_name):
"""获取最大行号"""
max_row_num=self.__wb[sheet_name].max_row
returnmax_row_num
defget_max_column_num(self,sheet_name):
"""获取最大列号"""
max_column=self.__wb[sheet_name].max_column
returnmax_column
defget_cell_value(self,sheet_name,coordinate=None,row=None,column=None):
"""获取指定单元格的数据"""
ifcoordinateisnotNone:
try:
returnself.__wb[sheet_name][coordinate].value
exceptExceptionase:
raisee
elifcoordinateisNoneandrowisnotNoneandcolumnisnotNone:
ifisinstance(row,int)andisinstance(column,int):
returnself.__wb[sheet_name].cell(row=row,column=column).value
else:
raiseTypeError('rowandcolumnmustbetypeint')
else:
raiseException("InsufficientCoordinateofcell!")
defget_row_value(self,sheet_name,row):
"""获取某一行的数据"""
column_num=self.get_max_column_num(sheet_name)
row_value=[]
ifisinstance(row,int):
forcolumninrange(1,column_num+1):
values_row=self.__wb[sheet_name].cell(row,column).value
row_value.append(values_row)
returnrow_value
else:
raiseTypeError('rowmustbetypeint')
defget_column_value(self,sheet_name,column):
"""获取某一列数据"""
row_num=self.get_max_column_num(sheet_name)
column_value=[]
ifisinstance(column,int):
forrowinrange(1,row_num+1):
values_column=self.__wb[sheet_name].cell(row,column).value
column_value.append(values_column)
returncolumn_value
else:
raiseTypeError('columnmustbetypeint')
defget_all_value_1(self,sheet_name):
"""获取指定表单的所有数据(除去表头)"""
max_row_num=self.get_max_row_num(sheet_name)
max_column=self.get_max_column_num(sheet_name)
values=[]
forrowinrange(2,max_row_num+1):
value_list=[]
forcolumninrange(1,max_column+1):
value=self.__wb[sheet_name].cell(row,column).value
value_list.append(value)
values.append(value_list)
returnvalues
defget_all_value_2(self,sheet_name):
"""获取指定表单的所有数据(除去表头)"""
rows_obj=self.__wb[sheet_name].iter_rows(min_row=2,max_row=self.__wb[sheet_name].max_row,values_only=True)
values=[]
forrow_tupleinrows_obj:
value_list=[]
forvalueinrow_tuple:
value_list.append(value)
values.append(value_list)
returnvalues
defget_excel_title(self,sheet_name):
"""获取sheet表头"""
title_key=tuple(self.__wb[sheet_name].iter_rows(max_row=1,values_only=True))[0]
returntitle_key
defget_listdict_all_value(self,sheet_name):
"""获取所有数据,返回嵌套字典的列表"""
sheet_title=self.get_excel_title(sheet_name)
all_values=self.get_all_value_2(sheet_name)
value_list=[]
forvalueinall_values:
value_list.append(dict(zip(sheet_title,value)))
returnvalue_list
defget_list_nametuple_all_value(self,sheet_name):
"""获取所有数据,返回嵌套命名元组的列表"""
sheet_title=self.get_excel_title(sheet_name)
values=self.get_all_value_2(sheet_name)
excel=namedtuple('excel',sheet_title)
value_list=[]
forvalueinvalues:
e=excel(*value)
value_list.append(e)
returnvalue_list
defwrite_cell(self,sheet_name,row,column,value=None,bold=True,color=BLACK):
ifisinstance(row,int)andisinstance(column,int):
try:
cell_obj=self.__wb[sheet_name].cell(row,column)
cell_obj.font=Font(color=color,bold=bold)
cell_obj.value=value
self.__wb.save(self.filename)
exceptExceptionase:
raisee
else:
raiseTypeError('rowandcolumnmustbetypeint')
if__name__=='__main__':
pe=ParseExcel('testdata.xlsx')
print(pe.get_all_value_2('division'))
print(pe.get_list_nametuple_all_value('division'))
column_row=pe.get_max_column_num('division')
print('最大列号:',column_row)
max_row=pe.get_max_row_num('division')
print('最大行号:',max_row)
cell_value_1=pe.get_cell_value('division',row=2,column=3)
print('第%d行,第%d列的数据为:%s'%(2,3,cell_value_1))
cell_value_2=pe.get_cell_value('division',coordinate='A5')
print('A5单元格的数据为:{}'.format(cell_value_2))
value_row=pe.get_row_value('division',3)
print('第{}行的数据为:{}'.format(3,value_row))
value_column=pe.get_column_value('division',2)
print('第{}列的数据为:{}'.format(2,value_column))
values_1=pe.get_all_value_1('division')
print('第一种方式获取所有数据\n',values_1)
values_2=pe.get_all_value_2('division')
print('第二种方式获取所有数据\n',values_2)
title=pe.get_excel_title('division')
print('表头为\n{}'.format(title))
dict_value=pe.get_listdict_all_value('division')
print('所有数据组成的嵌套字典的列表:\n',dict_value)
namedtuple_value=pe.get_list_nametuple_all_value('division')
print('所有数据组成的嵌套命名元组的列表:\n',namedtuple_value)
pe.write_cell('division',1,2,'Tc_title')
xlrd
安装xlrd,此模块只支持读操作,如果要写需要使用xlwt或者使用xlutils配合xlrd,但是使用xlwt只能对新的excel文件进行写操作,无法对原有文件进行写,所以这里选择是用xlutils
但是还有一个问题就是,如果使用xlutils,那么我们的excel文件需要以.xls为后缀。因为以xlsx为后缀无法实现写,会报错(亲测,因为formatting_info参数还没有对新版本的xlsx的格式完成兼容)
注:xlrd操作excel时,行号和列号都是从0开始计算的
封装代码
"""
------------------------------------
@Time:2019/5/1321:22
@Auth:linux超
@File:ParseExcel_xlrd.py
@IDE:PyCharm
@Motto:Realwarriors,daretofacethebleakwarning,daretofacetheincisiveerror!
------------------------------------
"""
importxlrd
fromxlutilsimportcopy
fromcollectionsimportnamedtuple
classParseExcel(object):
#xlrd解析excel,行号和列号都是从0开始的
def__init__(self,filename,sheet):
try:
self.filename=filename
self.sheet=sheet
self.wb=xlrd.open_workbook(self.filename,formatting_info=True)
ifisinstance(sheet,str):
self.sheet=self.wb.sheet_by_name(sheet)
elifisinstance(sheet,int):
self.sheet=self.wb.sheet_by_index(sheet)
else:
raiseTypeError('sheetmustbeintorstr')
exceptExceptionase:
raisee
defget_max_row(self):
"""获取表单的最大行号"""
max_row_num=self.sheet.nrows
returnmax_row_num
defget_max_column(self):
"""获取表单的最大列号"""
min_row_num=self.sheet.ncols
returnmin_row_num
defget_cell_value(self,row,column):
"""获取某个单元格的数据"""
ifisinstance(row,int)andisinstance(column,int):
values=self.sheet.cell(row-1,column-1).value
returnvalues
else:
raiseTypeError('rowandcolumnmustbetypeint')
defget_row_values(self,row):
"""获取某一行的数据"""
ifisinstance(row,int):
values=self.sheet.row_values(row-1)
returnvalues
else:
raiseTypeError('rowmustbetypeint')
defget_column_values(self,column):
"""获取某一列的数据"""
ifisinstance(column,int):
values=self.sheet.col_values(column-1)
returnvalues
else:
raiseTypeError('columnmustbetypeint')
defget_table_title(self):
"""获取表头"""
table_title=self.get_row_values(1)
returntable_title
defget_all_values_dict(self):
"""获取所有的数据,不包括表头,返回一个嵌套字典的列表"""
max_row=self.get_max_row()
table_title=self.get_table_title()
value_list=[]
forrowinrange(2,max_row):
values=self.get_row_values(row)
value_list.append(dict(zip(table_title,values)))
returnvalue_list
defget_all_values_nametuple(self):
"""获取所有的数据,不包括表头,返回一个嵌套命名元组的列表"""
table_title=self.get_table_title()
max_row=self.get_max_row()
excel=namedtuple('excel',table_title)
value_list=[]
forrowinrange(2,max_row):
values=self.get_row_values(row)
e=excel(*values)
value_list.append(e)
returnvalue_list
defwrite_value(self,sheet_index,row,column,value):
"""写入某个单元格数据"""
ifisinstance(row,int)andisinstance(column,int):
ifisinstance(sheet_index,int):
wb=copy.copy(self.wb)
worksheet=wb.get_sheet(sheet_index)
worksheet.write(row-1,column-1,value)
wb.save(self.filename)
else:
raiseTypeError('{}mustbeint'.format(sheet_index))
else:
raiseTypeError('{}and{}mustbeint'.format(row,column))
if__name__=='__main__':
pe=ParseExcel('testdata.xls','testcase')
print('最大行号:',pe.get_max_row())
print('最大列号:',pe.get_max_column())
print('第2行第3列数据:',pe.get_cell_value(2,3))
print('第2行数据',pe.get_row_values(2))
print('第3列数据',pe.get_column_values(3))
print('表头:',pe.get_table_title())
print('所有的数据返回嵌套字典的列表:',pe.get_all_values_dict())
print('所有的数据返回嵌套命名元组的列表:',pe.get_all_values_nametuple())
pe.write_value(0,1,3,'test')
pandas
pandas是一个做数据分析的库,总是感觉在自动化测试中使用pandas解析excel文件读取数据有点大材小用,不论怎样吧,还是把pandas解析excel文件写一下把
我这里只封装了读,写的话我这有点小问题,后面改好再追加代码吧。
请先pipinstallpandas安装pandas
封装代码
"""
------------------------------------
@Time:2019/5/1314:00
@Auth:linux超
@File:ParseExcel_pandas.py
@IDE:PyCharm
@Motto:Realwarriors,daretofacethebleakwarning,daretofacetheincisiveerror!
------------------------------------
"""
importpandasaspd
classParseExcel(object):
def__init__(self,filename,sheet_name=None):
try:
self.filename=filename
self.sheet_name=sheet_name
self.df=pd.read_excel(self.filename,self.sheet_name)
exceptExceptionase:
raisee
defget_row_num(self):
"""获取行号组成的列表,从0开始的"""
row_num_list=self.df.index.values
returnrow_num_list
defget_cell_value(self,row,column):
"""获取某一个单元格的数据"""
try:
ifisinstance(row,int)andisinstance(column,int):
cell_value=self.df.ix[row-2,column-1]#ix的行参数是按照有效数据行,且从0开始
returncell_value
else:
raiseTypeError('rowandcolumnmustbetypeint')
exceptExceptionase:
raisee
defget_table_title(self):
"""获取表头,返回列表"""
table_title=self.df.columns.values
returntable_title
defget_row_value(self,row):
"""获取某一行的数据,行号从1开始"""
try:
ifisinstance(row,int):
row_data=self.df.ix[row-2].values
returnrow_data
else:
raiseTypeError('rowmustbetypeint')
exceptExceptionase:
raisee
defget_column_value(self,col_name):
"""获取某一列数据"""
try:
ifisinstance(col_name,str):
col_data=self.df[col_name].values
returncol_data
else:
raiseTypeError('col_namemustbetypestr')
exceptExceptionase:
raisee
defget_all_value(self):
"""获取所有的数据,不包括表头,返回嵌套字典的列表"""
rows_num=self.get_row_num()
table_title=self.get_table_title()
values_list=[]
foriinrows_num:
row_data=self.df.ix[i,table_title].to_dict()
values_list.append(row_data)
returnvalues_list
if__name__=='__main__':
pe=ParseExcel('testdata.xlsx','testcase')
print(pe.get_row_num())
print(pe.get_table_title())
print(pe.get_all_value())
print(pe.get_row_value(2))
print(pe.get_cell_value(2,3))
print(pe.get_column_value('Tc_title'))
总结
使用了3种方法,4个库xlrd,openpyxl,xlwt,pandas操作excel文件,个人感觉还是使用openpyxl比较适合在自动化中使用,当然不同人有不同选择,用哪个区别也不是很大。
以上3种方法,都可以拿来直接使用,不需要再做封装了!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。