配置表测试框架搭建-②数据读取篇


前言

这篇为游戏策划配置表测试系列的第二篇,主要讲的是根据项目的配置表格规范或格式来读取对应的数据,比如读取Excel文件的所有数据、读取当个工作表的数据、按行读取、按列读取、按字段读取,用不同的库读取速度也不一样,之前也写过一篇读取速度对比的文章,这里跳转,我这主要用的openpyxl,其它几个库使用上差别不大;另外一个会用到Lua库,因为配置表里的数据有些直接配置成Lua的table或array,需要转换成Python的数据。

技术栈

语言:Python3.6.9
库:openpyxl、lupa、pathlib、datatime

openpyxl、lupa安装:

pip install openpyxl
pip install lupa

配置Demo

正文

一、工作表数据读取

按行读取的配置表结构看下图,参考一下

来实现一个方法获取对应的数据,
参数注释
table:Excel文件名
sheet_name:工作表名
start_row:从第几行开始读取,初始值是0
变量注释
self.floder_path:配置表文件夹路径
column_value:openpyxl读取后是cell对象,需要通过.value来获取

from openpyxl import load_workbook

    def get_sheet_data(self,table='道具配置表.xlsx',sheet_name='',start_row=6):
        '''获取工作表的数据'''
        wb = load_workbook(filename=f'{self.folder_path}{table}', data_only=True)
        sheet_datas = {}
        ws = wb[sheet_name]
        for column in list(ws.columns)[1:]:
            column_value = [i.value for i in column]
        	sheet_datas[column_value[start_row]] = column_value[start_row+1:]
        return sheet_datas

二、工作表屏蔽

上面的数据是没有经过筛选的,当出现不用的数据或工作表策划没有移除的时候,需要把这些数据屏蔽掉
参数注释
ws = wb[sheet]
变量注释
discard_sheet:列表的第一个值是Excel文件名,第二第三及后面的为工作表名,支持多个工作表屏蔽
单元格A3B3:用来标识工作表是按行还是按列来读取文件

    def _delete_discard_sheet(self,ws:any,sheet:str,table:str):
        '''屏蔽那些废弃的表'''
        discard_sheet = [['cfgDemo', 'baseRow', 'baseColumn']]
        if ws['B3'].value in [None,''] or ws['A3'].value != 'key数量' or '废弃' in sheet \
                or '不用' in sheet or '停用' in sheet:
            return False
        if table == 'cfgDemo.xlsx':
            # sheet主题颜色为1表示弃用
            sheet_prop = ws.sheet_properties.tabColor
            if sheet_prop:
                if sheet_prop.theme == 1:
                    return False
        for ds in discard_sheet:
            if ds[0] in table:
                for sh in ds[1:]:
                    if sh == sheet:
                        return False

三、筛选有效数据

我们除了要屏蔽工作表之外,可能还有很多冗余数据需要额外处理,比如一些废弃的字段;第N行,第N列的数据是不再引用的,需要兼容;这个方法要用到numpy的数组,相关的知识这里简单介绍下,需要更全面的自行百度哈。
np.delete:axis=0,按行删除
np.delete:axis=1,按列删除
np.where(condition, x, y):满足条件(condition),输出x,不满足输出y。
这里的参数与上面说的参数一致,不重复了
变量注释
**key_data:**我这里的KEY值也代表着从第几列作为有效数据的参考,例如KEY=2,有效列是B列。
where_none: 用来找出key_data空值的第一维坐标,然后移除无用数据
**思路:**按行来遍历整个工作表,碰到整行都是空的就停止,读完的数据转换成数组,再根据key值利用numpy.delete来删除无用的数据

import numpy as np

    def _get_valid_rows(self,ws,table='',start_row=5):
    	#key=0 按行读取,key>0 按列读取
        tag_row = ws['B3'].value
        try:
            if not isinstance(eval(str(tag_row)),int) or tag_row > 4:
                print('sheet key is empty', tag_row, table)
                return False
        except:return False
        def get_data(srow=start_row):
            rows_data = []
            for row in list(ws.rows)[srow:]:
                one_row_data = [i.value for i in row]
                if len(set(one_row_data)) == 1 and list(set(one_row_data))[0] == None:
                    break
                else:rows_data.append(one_row_data)
            return rows_data

        if tag_row != 0:
            data = np.array(get_data(),dtype=object)
            key_data = data[:,tag_row - 1]
            # 根据Key行来找出废弃行的位置
            where_none = np.where(key_data == None)
            data = np.delete(data,where_none[0][:],0)
            return data
        else:
            data = np.array(get_data(5), dtype=object)
            if len(data) > 0:
                key_data = data[:, 2]
                where_none = np.where(key_data == None)
                data = np.delete(data, where_none[0][:], 0)
                return (data,)
            else:return False

四、读取所有数据

上面定义两个方法 delete_discard_sheetget_valid_rows都在这里调用,这个函数利用sheetnames来获取所有的工作表名,结合两个方法遍历每个工作表,把所有数据存在变量all_sheet_data,方法最后return这个变量
变量注释
read_only: openpyxl的只读模式运行速度会快一些,需要了解的可以看我写的速度对比的文章
output_arg: 导入参数,用来区分前后端导出,如果该值为空则不读取数据

    def get_all_sheet(self,table='道具配置表.xlsx'):
        '''获取整个表格所有的sheet'''
        self.all_sheet_names = {}
        wb = load_workbook(filename=f'{self.folder_path}{table}', data_only=True, read_only=True)
        all_sheet_data = {}
        for sheet in wb.sheetnames:
            sheet_datas = {}
            ws = wb[sheet]
            if self._delete_discard_sheet(ws,sheet,table) == False:
                continue
            valid_data = self._get_valid_rows(ws,table=table)
            if isinstance(valid_data,bool) or len(valid_data) <= 0:
                continue
            if not isinstance(valid_data,tuple):
                if len(valid_data) <= 2:
                    continue
                output_arg = valid_data[0]
                # 获取字段
                field_list = valid_data[1]
                # 根据每字段列来插入数据
                for i in range(1,len(field_list)):
                    col_data = list(valid_data[2:,i])
                    if len(col_data) > 0 and field_list[i] != None and output_arg[i] in ['sc','c','s']:
                        sheet_datas[field_list[i]] = col_data
                    else:continue
            else:
                val_data = valid_data[0]
                for row_data in val_data:
                    if len(row_data[1:4]) > 0:
                        sheet_datas[row_data[2]] = [row_data[3]]
                    else:continue

            if len(sheet_datas) > 0:
                all_sheet_data[sheet] = sheet_datas
                self.all_sheet_names[sheet] = ws['B2'].value
            else:
                print('debug-> ', table, sheet)

        wb.close()
        return all_sheet_data

读完之后的数据结构,{“工作表”: {“字段名”: “字段数据”}…}
case

五、Lua数据处理

主要是针对lua的table和array来进行处理,转换成Python的字典,如果不需要转换则忽略。

from lupa import LuaRuntime

lua = LuaRuntime(unpack_returned_tuples=True)
lua.eval("{{type=0,id=1,count=1}}")

执行一下看看,从Excel读出来的字符串,转换到lua的table,再转换成Python的dict,这里的数据转换可以在读取表格数据时使用,也可以进行断言的时候使用。

>>>import lupa
>>>lua = lupa.LuaRuntime(unpack_returned_tuples=True)
>>>cell_data = "{{type=0,id=1,count=1}}"
>>>type(cell_data)
<class 'str'>
>>>lua_table = lua.eval(cell_data)
>>>type(lua_table)
<class 'lupa._lupa._LuaTable'>
>>>lupa.lua_type(lua_table)
'table'
>>>to_dict = dict(lua_table[1])
>>>to_dict
{'id': 1, 'count': 1, 'type': 0}

结语

上面这些都是前提准备工作,其实和策划配置表导出工具有些类似,之前也考虑要不要自己写脚本来读取配置表,直接用导表工具导出来后再进行读取,这样子省事,后面经过一轮比较后还是采取自己编写,自由度高一些。

欢迎小伙伴关注微信公众号ID:gameTesterGz
或关注我的CSDN:https://blog.csdn.net/qq_32557025
谢谢各位的关注、点赞!
微信二维码

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游戏测试-AJian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值