zoukankan      html  css  js  c++  java
  • 【QuotationTool的代码实现】framework部分

    项目链接:https://gitee.com/xyjtysk/quotationTools

    本章主要介绍framework的功能实现

    之前我们讲到,framework其实存放的是所有可以复用的代码,包括

    • 调用第三方库读写Excel

    • 对log工具的改进包

    • 对MySQL的操纵包

    代码结构

    我们先来看一下代码结构

    image.png

    功能函数

    function,includeList.py,pc.py都属于功能函数,也就是基本上每个项目里面都会有他们

    function.py

    function.py其实主要是为了M、V、C调用起来更为方便。

    我们希望M、V、C这三种类型的代码命名更为规范,比如

    • 业务模块M,我们希望它命名为类似“xxxxModelClass”这样,也就是“功能+Model+Class”这样。

    • 控制模块C,我们希望它类似"xxxxControllerClass"这样,把Controller带上

    • 视图模块V,我们也希望它能带上"xxxViewClass"字样

    既然这三者都这么规范了,我们何不使用一个统一的函数来调用了,这样更为简单 。

    于是对于Model的调用为,具体代码可参考python模块&类的导入

    其实就是根据字符串动态的导入相应的模块,最后进行实例化

    # name:字符
    # 作用:初始化Model
    def M(name):
        libs = __import__('libs.Model.'+name+'ModelClass');#动态的导入
        model = getattr(libs , "Model");#通过反射一步一步获得模块"xxxModelClass"
        testModelClass= getattr(model , name+'ModelClass');
        testModel = getattr( testModelClass, name+"Model");#通过反射获得类testModel
        return testModel();#实例化
    

    那么调用方法呢?
    比如

    rehandleInstance = M("rehandle");
    

    实际上它就是首先将libs.Model.rehandleModelClass这个模块加载进去了,然后调用rehandleModelClass()来进行实例化,赋给rehandleInstance

    对于View和Controller的实例化代码也类似。
    image.png

    includeList.py

    includeList.py把framework里面所有自定义的模块的加载语句都列出来。

    这样的好处就是,我在其他地方只需要加载includeList.py就可把framework里面的所有模块加载进来

    from  framework.includeList import  *
    

    includeList.py的详细代码:

    # !/usr/bin/env python3
    #encoding:UTF8
    # 将自定义的库加入
    from framework.libs.config.configParserClass   import *
    from framework.libs.excel.XlsReaderClass       import *
    from framework.libs.logutil.LogUtilsClass      import *
    from framework.libs.view.XlsWriterClass        import *
    from framework.libs.db.MySQLClass  import *
    from  framework.function.function import *
    
    

    pc.py

    pc.py的主要功能是提供一个对外调用的接口。

    我们可以在admin.py里面调用

    method = getParser("controller","method");
    pc.run("quotation",method);
    

    第1句指的是从配置文件里面读method方法是什么。

    然后调用pc.py中的run函数,把要执行的controller和method同时传递进去。

    也就是调用quotaitonControllerClass中的method方法。

    具体实现:

    # !/usr/bin/env python3
    #encoding:UTF8
    import os.path
    import os
    from  framework.includeList import  *
    
    
    def run(controller,method):
        C(controller,method);
        # C("quotation","index");
    
    

    image.png

    自定义函数

    在framework/libs里面存放的都是自定义函数。

    config/configParserClass.py

    configParserClass.py的作用是解析configure.conf文件的。

    如下为configure.conf中的一段代码

    [section]
    key=value
    

    其中 [section]称为域,可以将这个configure.conf文件划分成若干个逻辑上的模块,

    key=value本质上就是一个键值对。

    所以这个解析函数就是首先找到某个,然后去这个域里面通过key读取里面的value

    需要注意的是:

    configure.conf文件中不能存在两个相同的section和key

    那调用方法是就是

    getParser("section","key")
    

    第一个参数是section,第二个参数就是要取的key

    那么编写代码:

    #获取config配置文件
    # 配置文件格式
    # [section]
    # key=value
    def getParser (section, key):
        try:
            config = configparser.ConfigParser();
            # # 路径:当前文件上两层
            # os.path.dirname(__file__):获取当前文件的路径
            path = os.path.join(os.path.dirname(os.path.dirname (os.path.dirname(os.path.dirname(__file__)))),'configure.conf') ;
            # 文件格式:UTF-8
            config.read(path , 'UTF-8');
            
            value = config.get(section,key)
        except Exception as data:
            print("configure文件中存在两个相同的section"+str(data))
        return value
    

    代码的含义为,先找到configure.conf存放的路径,然后读取它,最后使用get函数来获得key对应的value值。

    logutil/LogUtilsClass.py

    我们平时要打印信息,可能最常用的就是print()函数了,但是在工程里面使用这个函数,多有不便。

    它最大的问题在于不能对信息分级

    怎么理解?

    比如说有些信息是错误信息,我应该在任何时候都显示,有些信息只是调试中用到信息,我希望在上线以后就关闭它,有些信息是为了给客户看的,作为一个提示。

    但是在python中就一个print()函数,无法很好的控制什么时候让它显示呢。

    所以我们可以定义4种信息打印级别:

    • DEBUG:表示调试信息

    • INFO:给用户展示的信息

    • ERROR:错误信息

    • NOTHING:啥都不显示

    DEBUG = 0;
    INFO = 1;
    ERROR = 2;
    NOTHING =3 ;
    

    设定当前的级别为level,我们可以从配置文件中读取

    level=int(getParser("loglevel","level"))
    

    如果当前的level为3,说明它处于NOTHING状态,其他信息当然不显示。

    也就是DEBUG,INFO,ERROR等信息只有在它大于level级别的时候才显示
    所以

        
    def debug(msg):
        if (DEBUG >= level):
            print(msg);
    
    def info (msg):
        if(INFO >= level):
            print(msg);
    
    def error (msg):
        if (ERROR >= level):
            print(msg);
    

    那么在打印信息的时候,如果此时我们想打印一个debug信息就可以

    debug("debug信息")
    

    当level设置为INFO的时候,因为level > DEBUG,所以不会显示。

    也就是说

    在开发的时候,我们可以把调试信息用debug()打印,level = DEBUG,此时正常输出。

    上线以后,我们把level级别设置为更高一级的,debug信息就不会打印了。

    excel/XlsReaderClass.py

    XlsReaderClass.py是使用xlrd模块进行Excel读取的。

    这个模块的具体使用方法可见:【python】python读excel-xlrd

    数据结构

    那么我们希望读出来的数据是这个什么样子呢?也就是数据结构是怎么样的?

    既然Excel是个二维表格,那么读出来的数也放在一个二维表格里面得了。

    产品编码 产品型号 数量 标准价(RMB)
    0235A0W2 RT-MSR5660 2 50000

    这样的缺点在于:取每个元素,需要计算index,不方便编程。

    比如我们要取第三行的“RT-MSR5660”,我们需要使用a[1][1]来取,非常不方便。

    我们知道最方便取的数据结构为dict,只要传进去一个key,它就会返回一个value,这样的好处是

    • 可以为每一列赋予实际的含义,比如说可以把产品型号的key设为BOM,我们要取“RT-MSR5660”的时候,就可以用a[1]['BOM']

    • 如果要调换列的顺序,可以轻松做到,更为的灵活

      因为每一列赋予了实际的含义,我们根本不用担心具体的顺序

    那么具体的数据格式应该是怎么样的呢?

    [
    {"BOM":"产品编码",    
    "typeID":"产品型号",    
    "description":"项目名称",    
    "totalQuantity":"数量",    
    "unitsNetListPrice":"标准价(RMB)"},
    
    {"BOM":"0235A0W2",    
    "typeID":"RT-MSR5660",   
    "description":"H3C MSR 56-60路由器机框",   
    "totalQuantity":"2",    
    "unitsNetListPrice":"50000"}
    ]
    
    • 原始表格中的每一行为一个dict

    • 所有行组成一个list

    从Excel中读数据

    既然现在数据结构已经设计好了,我们就来看如何读数据,并形成这样的数据结构吧。

    首先引入模块

    import xlrd
    

    然后定义一个操作类

    class XlrdTool(XlsReader):
        # 作用:获取关联数组
        # inputHeaderKey:数组每一列的对应的键值
        # 返回:一个数组,数组的每一行为一个dict,代表原来表格里面的每一行,其中此dict的键名为输入的inputHeaderKey,键值为读入的excel文件的对应值。
        
        def getAssociativeArray (self, excelPathName, sheetName , inputHeaderKey):
            list = []
            try:
                sheetList = xlrd.open_workbook(excelPathName).sheet_by_name(sheetName);
                # row:表示从当前sheet读出了的每一行,
                # 将每一行的row_values与inputHeaderKey组成dict
                list = [dict (zip (inputHeaderKey , sheetList
                .row_values(row))) for row in range(sheetList.nrows)];
                
            except Exception as data:
                print("打开文件失败,%s" % data);
            return list;
    

    里面最关键的代码其实只有:

    list = []
     sheetList = xlrd.open_workbook(excelPathName).sheet_by_name(sheetName);
     list = [dict (zip (inputHeaderKey , sheetList
                .row_values(row))) for row in range(sheetList.nrows)];
    

    我们来一一看看。

    • 从Excel中的某个sheet里面读出数据,xlrd.open_workbook(excelPathName).sheet_by_name(sheetName)

    • [dict (zip (inputHeaderKey , sheetList .row_values(row))) for row in range(sheetList.nrows)];我们可以拆解一下:

      • 这是一个列表生成式,for row in range(sheetList.nrows)表示对读出来的数组的每一行 row 进行遍历,

      对其中某一行row

      • 首先使用xlrd中的函数row_values取出每一行的值

      • inputHeaderKey表示为每一列赋予的一个key,它是一个数组。

      • 然后使用zip把读出来的每一行与inputHeaderKey组成键值对,再在外面迁套dict形成一个字典。
        也就是

    {"BOM":"0235A0W2",    
    "typeID":"RT-MSR5660",   
    "description":"H3C MSR 56-60路由器机框",   
    "totalQuantity":"2",    
    "unitsNetListPrice":"50000"}
    
    • 所有的dict形成一个列表
  • 相关阅读:
    pat甲级 1155 Heap Paths (30 分)
    pat甲级 1152 Google Recruitment (20 分)
    蓝桥杯 基础练习 特殊回文数
    蓝桥杯 基础练习 十进制转十六进制
    蓝桥杯 基础练习 十六进制转十进制
    蓝桥杯 基础练习 十六进制转八进制
    51nod 1347 旋转字符串
    蓝桥杯 入门训练 圆的面积
    蓝桥杯 入门训练 Fibonacci数列
    链表相关
  • 原文地址:https://www.cnblogs.com/dy2903/p/8465920.html
Copyright © 2011-2022 走看看