Python模块之openpyxl模块读数据、random随机数模块、hashlib加密模块、subprocess模块、日志模块

openpyxl模块读数据

>>> from openpyxl import load_workbook
>>>
>>> wb = load_workbook(r'aaa.xlsx',data_only = True)
>>> wb1 = wb['成绩表']
>>>
>>> for j in wb1.columns:
...     print([i.value for i in j])
...
['username', 'kwan1', 'kwan2', 'kwan3', 'kwan4', None]
['password', 123, 123, 123, 123, 123]
['age', 18, 18, 18, 18, 18]
['gender', 'female', 'female', 'female', 'female', 'female']
['hobby', 'read', 'read', 'read', 'read', None]
>>>
>>> print(wb1.max_row)  # 当前表格最大行数
6
>>> print(wb1.max_column)  # 当前表格最大列数
5
>>> print(wb1['B3'].value)  # 单元格B3的数据值
123
>>> print(wb1.cell(row=2,column=2).value) # 另一种写法
123

在使用 load_workbook 函数时有几个可供选择。

  • data_only 控制具有公式的单元格是否具有公式(默认)或上次 Excel 读取工作表时存储的值。
  • keep_vba 控制是否保留任何 Visual Basic 元素(默认)。 如果它们被保留,它们仍然不可编辑。

pandas模块

openpyxl不擅长读数据,pandas模块优化了读取的方式

# 封装了openpyxl的pandas模块操作excel表格的方式
>>> import pandas
>>>
>>> d = {
...     '公司名称': ['老男孩', '老女孩', '老伙计', '老北鼻'],
...     '公司地址': ['上海', '深圳', '杭州', '东京'],
...     '公司电话': [120, 130, 129, 996],
... }
>>>
>>> df = pandas.DataFrame(d)  # DataFrame 是一个表格型的数据结构
>>> df.to_excel(r'222.xlsx')  # 写入数据
>>> print(df)
  公司名称 公司地址  公司电话
0  老男孩   上海   120
1  老女孩   深圳   130
2  老伙计   杭州   129
3  老北鼻   东京   996

random随机数模块

  • random 模块主要用于生成随机数
  • random 模块实现了各种分布的伪随机数生成器。

random 模块方法

方法 描述
random() 返回 [0.0, 1.0) 范围内的下一个随机浮点数。
randint(a, b) 返回随机整数 N 满足 a <= N <= b。
choice(seq) 从非空序列 seq 返回一个随机元素。 如果 seq 为空,则引发 IndexError。
sample(population, k, *, counts=None) 返回从总体序列或集合中选择的唯一元素的 k 长度列表。 用于无重复的随机抽样。(随机抽样,自定义抽取个数)
shuffle(x[, random]) 将序列 x 随机打乱位置,序列的所有元素随机排序。

>>> import random
>>> print(random.random())
0.5084675741665274
>>> print(random.randint(1, 6))
4
>>>
>>> print(random.random())  # 返回0到1之间随机的小数
0.09145518099810934
>>>
>>> print(random.randint(1, 6))  # 返回1到6之间随机的整数(掷骰子)
3
>>>
>>> print(random.choice(['一等奖', '特等奖', '三等奖', '谢谢惠顾']))  # 随机抽取一个
特等奖
>>> print(random.sample(['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff', 'ggg'], 3))  # 随机抽样 自定义抽取个数
['ggg', 'eee', 'bbb']
>>>
>>> l1 = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A', '大王', '小王']
>>> random.shuffle(l1)  # 随机排序
>>> print(l1)
['J', 10, '小王', 8, 2, '大王', 'K', 3, 9, 6, 'A', 5, 'Q', 4, 7]

实例

"""搜狗python工程师笔试题"""
>>> code = ''  # 定义全局变量用于存储所有的验证码
>>> # 编写python代码 产生五位随机验证码(数字、小写字母、大写字母)
>>> for i in range(5):
...     # 每次循环都应该产生 数字 小写字母 大写字母
...     random_int = str(random.randint(0, 9))  # 随机产生一个数字
...     random_lower = chr(random.randint(97, 122))  # 随机产生一个小写字母
...     random_upper = chr(random.randint(65, 90))  # 随机产生一个大写字母
...     # 从上述三个数据值中随机挑选一个作为验证码的一位数据
...     temp = random.choice([random_int, random_lower, random_upper])
...     code += temp  # 拼接字符串
...
>>> print(code)
JR1Vt

# 封装
>>> def get_code(n):
...     code = ''  # 定义全局变量用于存储所有的验证码
...     # 编写python代码 产生五位随机验证码(数字、小写字母、大写字母)
...     for i in range(n):
...         # 每次循环都应该产生 数字 小写字母 大写字母
...         random_int = str(random.randint(0, 9))  # 随机产生一个数字
...         random_lower = chr(random.randint(97, 122))  # 随机产生一个小写字母
...         random_upper = chr(random.randint(65, 90))  # 随机产生一个大写字母
...         # 从上述三个数据值中随机挑选一个作为验证码的一位数据
...         temp = random.choice([random_int, random_lower, random_upper])
...         code += temp  # 拼接字符串
...     return code
...
>>> res = get_code(4)  # 自定义长度 4
>>> print(res)
mObx
>>> res1 = get_code(10)  # 自定义长度 10
>>> print(res1)
LqQDZ9NppI

hashlib加密模块

hashlib模块为各种不同的安全散列和消息摘要算法实现了一个通用接口。 现代术语是安全哈希。

  1. 什么是加密

    将明文数据(看得懂)经过处理之后变成密文数据(看不懂)的过程

  2. 为什么要加密

    不想让敏感的数据轻易的泄露

  3. 如何判断当前数据值是否已经加密

    一般情况下如果是一串没有规则的数字字母符合的组合一般都是加密之后的结果

  4. 加密算法

    就是对明文数据采用的加密策略

    不同的加密算法复杂度不一样,得出的结果长短也不一样

    通常情况下加密之后的结果越长,说明采用的加密算法越复杂

  5. 常见加密算法

    • md5
    • sha系列
    • hmac
    • base64

>>> import hashlib
>>>
>>> md5 = hashlib.md5()  # 选择md5加密算法作为数据的加密策略,构造一个hashlib的对象
>>> md5.update(b'123')  # 往里面添加明文数据,数据必须是bytes类型。update对指定字符串进行加密
>>> res = md5.hexdigest()  # 获取加密之后的结果
>>> print(res)
202cb962ac59075b964b07152d234b70

加密模块补充说明

  • 加密之后的结果一般情况下不能反解密

    202cb962ac59075b964b07152d234b70
    """
    所谓的反解密很多时候其实是偷换概念:
        1. 提前假设别人的密码是什么,然后用各种算法算出对应的密文
        2. 构造对应关系,然后比对密文,最终映射明文
            {'密文1':123,'密文2':321,...}
    """
    
  • 只要明文数据是一样的那么采用相同的算法得出的密文肯定一样

    >>> import hashlib
    >>>
    >>> md5 = hashlib.md5()
    >>> md5.update(b'123')
    >>> md5.update(b'hello')
    >>> md5.update(b'kwan')
    >>> res = md5.hexdigest()
    >>> print(res)
    fd658a20a233608a3543a8e2f89ce54b
    >>>
    >>> md5 = hashlib.md5()
    >>> md5.update(b'123hellokwan')
    >>> res = md5.hexdigest()
    >>> print(res)
    fd658a20a233608a3543a8e2f89ce54b
    
  • 加盐处理(salt)

    增加干扰项

    >>> import hashlib
    >>>
    >>> password = input('password>>>:').strip()
    password>>>:123456
    >>>
    >>> md5.update('公司设置的盐(干扰项)'.encode('utf8'))
    >>> md5.update(password.encode('utf8'))
    >>> res = md5.hexdigest()
    >>> print(res)
    7e90126464597f75bfee43fcfdfdd365
    
  • 动态加盐(salt)

    干扰项每次都不一样

    eg:
        每次获取当前时间 每个用户用户名截取一段
    

加密实际应用场景

  1. 用户密码加密

    注册存储密文,登录也是比对密文

  2. 文件安全性校验

    正规的软件程序写完之后做一个内容的加密

    网址提供软件文件记忆该文件内容对应的密文

    用户下载完成后不直接运行,而是对下载的内容做加密

    然后比对两次密文是否一致,如果一致表示文件没有被改,不一致则表示改程序有可能被植入病毒

  3. 大文件加密优化

    程序文件100G

    ​ 一般情况下读取100G内容然后全部加密,太慢

    ​ 不对100G所有的内容加密,而是截取一部分加密

    ​ eg:每隔500M读取30bytes

subprocess模块

模拟计算机cmd命令窗口

import subprocess

cmd = input('请输入您的指令>>>:').strip()
sub = subprocess.Popen(cmd,
                       shell=True,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE
                       )
# stdout执行命令之后正确的返回结果
print(sub.stdout.read().decode('gbk'))
# stderr执行命令报错之后的返回结果
print(sub.stderr.read().decode('gbk'))

日志模块

日志模块需要自己写的代码很少,几乎都是CV

  1. 什么是日志

    日志就类似于是历史记录

  2. 为什么要使用日志

    为了记录事物发生的事实(史官)

日志等级

import logging

logging.debug('debug等级')  # 10
logging.info('info等级')  # 20
logging.warning('warning等级')  # 默认从warning级别开始记录日志  30
logging.error('error等级')  # 40
logging.critical('critical等级')  # 50

>>> 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('我不好!!!')
ERROR:root:我不好!!!

日志配置字典

import logging.config

# 定义日志输出格式 开始
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]'  # 其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

# 自定义文件路径
logfile_path = 'log.log'
# log配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format
        },
    },
    'filters': {},  # 过滤日志
    'handlers': {
        # 打印到终端的日志
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        # 打印到文件的日志,收集info及以上的日志
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',
            'filename': logfile_path,  # 日志文件
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
            'backupCount': 5,
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
    },
    'loggers': {
        # logging.getLogger(__name__)拿到的logger配置
        '': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': True,  # 向上(更高level的logger)传递
        },  # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
        # '购物车记录': {
        #     'handlers': ['default','console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
        #     'level': 'WARNING',
        #     'propagate': True,  # 向上(更高level的logger)传递
        # },  # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
    },
}

logging.config.dictConfig(LOGGING_DIC)  # 自动加载字典中的配置
logger1 = logging.getLogger('购物车记录')
logger1.warning('尊敬的VIP客户 晚上好 您又来啦')
logger1 = logging.getLogger('注册记录')
logger1.debug('jason注册成功')
logger1 = logging.getLogger('红浪漫顾客消费记录')
logger1.debug('慢男 猛男 骚男')

实例

# 按照软件开发目录规范编写使用
  """配置文件中变量名推荐全大写"""
该案例能够带你搞明白软件开发目录规范中所有py文件的真正作用

def get_logger(msg):
    # 记录日志
    logging.config.dictConfig(settings.LOGGING_DIC)  # 自动加载字典中的配置
    logger1 = logging.getLogger(msg)
    # logger1.debug(f'{username}注册成功')  # 这里让用户自己写更好
    return logger1
  • 日志字典数据应该放在某个py文件内
  • 字典数据是日志模块固定的配置,写完一次之后几乎都不需要动
  • 日志属于配置文件
posted @ 2022-07-21 22:03  梦想有双休  阅读(100)  评论(0)    收藏  举报