zoukankan      html  css  js  c++  java
  • 包的使用

    包的使用

    什么是包

    # 官方解释
    Packages are a way of structuring Python’s module namespace by using “dotted module names”
    包是一种通过使用‘.模块名’来组织python模块名称空间的方式。
    
    # 具体的:包是一系列模块的结合体,表示形式就是一个文件夹 该文件内部通常会有一个__init__.py文件,包的本质还是一个模块。
    
    #需要强调的是:
      1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
    
      2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是一种模块
    
    • 为何要使用包
    包的本质就是一个文件夹,那么文件夹唯一的功能就是将文件组织起来
    随着功能越写越多,我们无法将所以功能都放到一个文件中,于是我们使用模块去组织功能,而随着模块越来越多,我们就需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性
    
    • 导入包的执行流程
    # 首次导入包
    	先产生一个执行文件的名称空间
    		1. 创建包下面的__init__.py文件的名称空间
    		2. 执行包下面的__init__.py文件中的代码,将产生的名字放入包下面的__init__.py文件名称空间中
    		3. 在执行文件中拿到一个指向包下面的__init__.py文件名称空间的名字
    
    • 注意:
    当作为包的设计者来说:
    	1. 当模块的功能特别多的情况下 应该分文件管理
    	2. 每个模块之间为了避免后期模块改名问题 可以使用相对导入(包里面的文件都应该是被导入的模块)
    
    站在包的开发者来说  如果使用绝对路径来管理自己的模块 那么它只需要永远以包的路径为基准一次导入模块
    站在包的使用者来说  必须将包所在的文件夹路径添加至系统环境变量中
    

    logging模块

    • 日志级别
    import logging
    logging.debug('debug日志')
    logging.info('info日志')
    logging.warning('warning日志')
    logging.error('error日志')
    logging.critical('critical日志')
    
    默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING
    (日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG),默认的日志格式为日志级别:Logger名称:用户输出消息。
    
    • 日志对象
    1. logger对象:负责产生日志
    2. filter对象:过滤日志
    3. handler对象:控制日志输出的位置
    4. formater对象:规定日志内容的格式
    

    灵活配置日志级别,日志格式,输出位置:

    import logging
    
    file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',)
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        handlers=[file_handler,],
        level=logging.ERROR
    )
    
    logging.error('你好')
    

    日志切割

    import time
    import logging
    from logging import handlers
    
    sh = logging.StreamHandler()
    rh = handlers.RotatingFileHandler('myapp.log', maxBytes=1024,backupCount=5)
    fh = handlers.TimedRotatingFileHandler(filename='x2.log', when='s', interval=5, encoding='utf-8')
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        handlers=[fh,sh,rh],
        level=logging.ERROR
    )
    
    for i in range(1,100000):
        time.sleep(1)
        logging.error('KeyboardInterrupt error %s'%str(i))
    

    配置参数

    logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
    
    filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
    filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
    format:指定handler使用的日志显示格式。
    datefmt:指定日期时间格式。
    level:设置rootlogger(后边会讲解具体概念)的日志级别
    stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),
    默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
    
    format参数中可能用到的格式化串:
    %(name)s Logger的名字
    %(levelno)s 数字形式的日志级别
    %(levelname)s 文本形式的日志级别
    %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
    %(filename)s 调用日志输出函数的模块的文件名
    %(module)s 调用日志输出函数的模块名
    %(funcName)s 调用日志输出函数的函数名
    %(lineno)d 调用日志输出函数的语句所在的代码行
    %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
    %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
    %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    %(thread)d 线程ID。可能没有
    %(threadName)s 线程名。可能没有
    %(process)d 进程ID。可能没有
    %(message)s用户输出的消息
    

    logger对象配置

    import logging
    
    logger = logging.getLogger()
    # 创建一个handler,用于写入日志文件
    fh = logging.FileHandler('test.log',encoding='utf-8') 
    
    # 再创建一个handler,用于输出到控制台 
    ch = logging.StreamHandler() 
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setLevel(logging.DEBUG)
    
    fh.setFormatter(formatter) 
    ch.setFormatter(formatter) 
    logger.addHandler(fh) #logger对象可以添加多个fh和ch对象 
    logger.addHandler(ch) 
    
    logger.debug('logger debug message') 
    logger.info('logger info message') 
    logger.warning('logger warning message') 
    logger.error('logger error message') 
    logger.critical('logger critical message')
    

    hashlib模块

    • 算法介绍
    Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。
    
    什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
    
    摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。
    
    摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。
    
    我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:
    
    import hashlib
    
    md5 = hashlib.md5()				# 生成一个帮助造密文的对象
    md5.update('how to use md5 in python hashlib?')	# 往对象里面传明文数据 update只能接受bytes类型的数据
    print md5.hexdigest()			        # 获取明文数据对应的密文   
    
    计算结果如下:
    5d41402abc4b2a76b9719d911017c592
    
    MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似:
    import hashlib
     
    sha1 = hashlib.sha1()
    sha1.update('how to use sha1 in ')
    sha1.update('python hashlib?')
    print sha1.hexdigest()
    
    SHA1的结果是160 bit字节,通常用一个40位的16进制字符串表示。比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度更长
    
    • 应用场景
    # hashlib模块应用场景
        1.密码的密文存储
        2.效验文件内容是否一致
    
    • 加盐处理

      由于常用口令的MD5值很容易被计算出来,所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”

    def get_md5(data):							# 封装成函数方便下次调用
        md = hashlib.md5()						        # 使用md5的加密方式
        md.update('自己加的盐'.encode('utf-8'))                              # 将对象中传入自己加的盐
        md.update(data.encode('utf-8'))			                # 将函数中传参传入对象中
        return md.hexdigest()					        # 获取明文数据对应的密文
    password = input('清输出你需要加密的值>>>:')    
    res = get_md5(password)						        # 将变量传入函数中直接调用
    print(res)							        # 打印加密结果
    

    openpyxl模块

    • 使用模块写文件
    # openpyxl 比较火的操作excel的模块
    
    """
    excel 03版本前后缀名叫 xlx
    excel 03版本后后缀名叫 xlsx
    
    xlwd    写excel
    xlrt    读excel
    
    xlwd和xlrt既支持03版本之前的excel文件也支持03版本之后的excel文件
    openpyxl 只支持03版本会后的xlsx
    """
    
    from openpyxl import Workbook
    wb = Workbook                   	# 生成一个工作簿
    wb1 = wb.create_sheet('index',0)  	# 创建表index表单页,控制表单位置
    wb2 = wb.create_sheet('index1',2)  	# 创建表index1表单页,控制表单位置
    wb1.title = 'login'                     # 修改表单页的名称为login
    
    
    wb1.cell(row=6,column=3,value=888888)           # 在表单index的第六行第三列添加内容888
    # wb1['A3'] = 666                 		# 在表单index的A3位置写入内容666
    # wb1['A4'] = 444                 		# 在表单index的A4位置写入内容444
    # wb1['A5'] = '=sum(A3:A4)'       		# 在表单A5位置对A3和A4进行求和
    
    wb1.append(['username','age','hobby'])      # 添加表头
    wb1.append(['jason',18,'study'])            # 对应表头添加内容
    wb1.append(['tank',11,'read'])              # 对应表头添加内容
    wb1.append(['agon',22,'女教练'])             # 对应表头添加内容
    
    wb.save('test,xlsx')                         # 保存工作簿起名为test
    
    • 读文件
    from openpyxl import load_workbook                              # 读文件
    
    wb = load_workbook('test.xlsx',read_only=True,data_only=True)   # data_only表示只读数据,不读公式
    print(wb.sheetnames)                                            # 打印表单页名称
    print(wb['login']['A3'].value)                                  # 查看表单页login A3位置对应的值
    print(wb['login']['A5'].value)                                  # 查看表单页login A3位置对应的值
    
    res = wb['login']
    ge1 = res.rows
    for i in ge1:
        for j in i:
            print(j.value)
    

    copy模块

    import copy
    # l = [1,3,[1,2]]
    # l1 = copy.copy(l)         # 拷贝一份,浅拷贝
    # print(id(l),id(l1))       # 2123774630408 2123774630472 拷贝出来的文件与源文件di并不一致
    # # l[0] = 222              # 仅针对l的索引0修改数据
    # # print(l,l1)             # [222, 3, [1, 2]] [1, 3, [1, 2]]
    # l[2].append(666)          #
    # print(l,l1)               # [1, 3, [1, 2, 666]] [1, 3, [1, 2, 666]]
    
    # 浅拷贝说明:
    #仅仅是拷贝了一份和源文件同样的数据,但是实则上指向的内容还是和源文件一致,针对源文件进行修改,如上例,如修改源文件,针对不可变类型,源文件会断掉指向内容的值重新指向,而可变类型
    
    l = [1,2,[1,2]]
    l1 = copy.deepcopy(l)
    l[2].append(666)
    print(l,l1)                     # [1, 2, [1, 2, 666]] [1, 2, [1, 2]] 深拷贝,源文件新增,新文件并不修改
    
    # 深拷贝说明:
    #拷贝和源文件一样的数据,但是和浅拷贝不一样之处在于,深拷贝对于可变类型会新建内容,再将内容进行指向,这样对于源文件的可变类型修改,并不会改变新文件
    #对于可变不可变到底是指向原来的内容,还是新建内容
    
  • 相关阅读:
    C# 设计原则-单一职责原则
    C# Linq的简单运用
    .Net Core中的管道机制
    .Net Core和.Net Framework的区别
    C# 9.0 新特性简析
    .Net core的依赖注入
    .Net IOC容器unity的使用
    网站被黑客攻击百度出现警示
    七牛云免费对象存储(解决图片加载缓慢问题)
    今天第一篇博客 说点随意的内容
  • 原文地址:https://www.cnblogs.com/tcy1/p/14506219.html
Copyright © 2011-2022 走看看