zoukankan      html  css  js  c++  java
  • 第六章 模块

    6.1 模块的基本知识

    1. 模块的导入

    1. 模块:可以是py文件也可以是文件夹
      • py文件,写好了的对程序员直接提供某方面功能
      • import / from xxx import xx
      • :存储了多个py文件的文件夹,pickle,json,urlib
      • 如果导入一个包,包里默认模块是不能使用的
        • 导入一个包相当于执行__init__.py文件内容
    2. 定义模块时,可以把一个py文件或一个包当作一个模块,以便于以后其他py文件使用。
    3. __ init__.py 在文件夹中创建此py文件, python packages
      • py2:文件夹中必须有__ init__.py
      • py3:不需要,推荐加上
    4. 导入模块
      1. 导入模块—>调用模块中的函数(import 文件名)
      2. import 会把模块中的文件加载到内存
      3. from py文件名 import func,show… (*):只导入指定函数,也会把模块中的内容加载一遍
        • 模块中的函数名可能和本地函数重名
        • from 模块 import func as f(模块中的函数重命名) f()
    # test为文件夹,在当前工作目录中,jd为py文件,f1为jd中的函数
    import test.jd
    test.jd.f1()
    # test为文件夹,在当前工作目录中,jd为py文件,f1为jd中的函数
    from test import jd
    jd.f1()
    
    # 导入(绝对导入、相对. /..导入:相对导入必须有父籍包
    # import
    # from 模块.模块 import 模块
    # from 模块.模块.模块 import 函数
    # 调用:模块.函数(),函数()
    # 主文件:运行的文件(print(__name__)). 
    if __name__ == '__main__
    

    Note1(4)

    1. 模块在和要执行的py文件在同一路径且需要很多功能时,推荐使用import 模块
    2. 其他推荐:from 模块 import 模块
    3. from 模块1.模块2 import 函数 执行:函数()
    4. 文件(夹)命名不可与模块相同,否则就会用当前目录中的文件(夹)
    # __file__ python命令行中获取的参数
    import os
    import sys
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))
    sys.path.append(BASE_DIR)
    

    2. 分类(3)

    • 内置模块(py内部提供的功能)

    • 第三方模块

    # pip 安装模块
    pip install module_name
    # 安装成功,如果导入不成功,需要重启pycharm 
    
    • 自定义模块
    # a.py
    def f1():
      pass
    def f2():
      pass 
    
    # 调用自定义模块中的功能
    import a
    a.f1()
    

    6.2 内置模块(10)

    • 内置模块目前有randomhashlibgetpasssys相关,os相关,shutiljsontime&datetime, import lib, logging10个。

    1. random(7)

    # random.randint(a, b)
    import random
    def get_random_data(length=6):
        data = []
        for i in range(length):
            v = chr(random.randint(65, 90)).lower()  # 得到一个随机数
            data.append(v)
        return ' '.join(data)
    
    1. random.randint(1,5):包含两边
    2. random.choice([1, 2, 3]):随机选择一个:验证码,抽奖
    3. random.sample([1, 2, 3, 4, 5], 3):随机选3个不重复,抽奖多个人
    4. random.uniform(1, 5):随机1-5中的随机小数
    5. random.shuffle([1,2,3,4]):洗牌,算法
    6. random.random():随机生成[0-1)之间的数
    7. random.randrange(1,5):randint基于randrange

    2. hashlib(1) / getpass

    摘要算法模块,密文验证/校验文件独立性

    note1(3)

    1. md5 / sha
    2. 摘要文件内容一样,无论怎么分割,md5摘要后一致(大文件一致性校验)
    3. 一般在服务端进行加盐,给每个用户使用不同的salt,可以借助用户名
    # 将指定的**str**摘要,可以使用sha1/md5
    # md5常用来文件完整性校验
    # hashlib.md5()/ .update() /.hexdigest()
    import hashlib
    def get_md5(data):
        obj = hashlib.md5()
        obj.update(data.encode('utf-8'))
        return obj.hexdigest()
    val = get_md5('123')
    print(val)
    

    加盐

    import hashlib
    def get_md5(data):
        obj = hashlib.md5('adsfg12fsg'.encode('utf-8'))
        obj.update(data.encode('utf-8'))
        return obj.hexdigest()
    val = get_md5('123')
    print(val)
    

    密码不显示

    import getpass
    pwd = getpass.getpass('please input pwd: ')
    print(pwd)
    

    3. time(2)

    import time
    v = time.time() # 获取从1970年开始到目前的时间,单位为秒
    time.sleep(2)  	# 休眠时间,2秒
    

    4. sys (6)

    • 解释器相关
    1. sys.getrefcount(a)
    2. sys.recursionlimit() / sys.setrecursionlimit()
    3. sys.stdout.write(). print—>进度条
    4. sys.argv:获取命令行参数
      • shutil(shutil.rmtree(path)
    5. sys.path:模块导入路径
    6. sys.modules:存储当前程序中用到的所有模块
    # 引用计数器
    import sys  
    a = [1, 2, 3]
    print(sys.getrefcount(a))
    
    # python默认支持的递归数量
    v = sys.getrecrusionlimit()
    
    # 输入输出,默认换行
    sys.stdout.write('hello')
    # 
     	 
    # 
    : 回到当前行的起始位置,一般于end=‘’连用
    print('123
    ', end='')
    print('hello', end='')   
    # 在输出的时候,回到123前,重新打印
    # 应用:进度条
    
    • sys.argv / shutil
    # sys.argv  shutil
    # 删除 目录 的脚本, 只能是directory
    import sys
    import shutil
    
    path = sys.argv[1]
    shutil.rmtree(path)
    print('remove the %s' % path)
    
    • sys.path(是个list)
      • paython解释器会按sys.pathon的路径查找
    # sys包含python 和 工作目录
    # 当前py文件所在路径会加载到 sys.path中
    # pycharm也会 自动添加工作目录 和 项目路径加入
    # python导入模块时默认查找路径
    # 只能导入目录下的第一层文件
    
    sys.path.append('module_path')
    

    5. os(操作系统相关)(16)

    1. os.path.exist(file_name)
    2. os.stat(file_name).st_size
    3. os.path.abspath(file_name)
    4. os.path.dirname(file_name) # 获取上级目录
    5. os.path.join() # 路径拼接
    6. os.listdir() # 指定目录下的第一层文件,默认path = '.'
    7. os.walk(r'path')
    8. os.mkdir() / os.makedirs()
    9. os.rename(a, b)
    10. os.remove(a)
    11. os.path.isdir()
    12. os.path.isfile()
    13. os.path.isabs()
    14. os.path.basename():获取绝对路径下的文件名
    15. os.getpid():获取进程的id
    16. os.getppid():获取其父进程的id
    import os
    1. 获取文件大小
    fiel_size = os.stat('filename').st_size   # 单位为字节
    2. 读取文件
    chunk_size = 1024
    with open('filename', mode='rb') as f1:
      
    v = r'path'  # r 表示转义,包括所有
    os.path.dirname(v)
    
    转义
    v = 'al\nex'
    v = r'al
    ex'  # 推荐
    
    import os
    v = 'test.txt'
    path = 'user/henry/desktop'
    new_path = os.path.join(path, v)
    
    # 当前目录下第一层文件
    import os
    result = os.listdir(r'path')
    print(result)
    
    # 当前目录下的所有文件
    import os
    result = os.walk(r'path')   # 生成器
    for a, b, c in result: 
      for i in c:  # a 是目录;b 是目录下的文件夹;c 是目录下的文件
        path = os.path.join(a, i)
          print(path)
    

    6. shutil(4)

    1. shutil.make_archive()
    2. shutil.unpack_archive()
    3. shutil.rmtree()
    4. shutil.move()
    import shutil
    shutil.rmtree(r'path')
    
    import shutil
     # 没有返回值
    shutil.rmtree('dir_name')
    # 重命名,可以是文件/目录
    shutil.move('file_name1', 'new_file_name')
    # 压缩文件(c_file_name.zip), 如果只给定文件名,压缩到py脚本所在目录
    shutil.make_archive('c_file_name', 'zip', 'dir_name')
    # 解压文件,默认是当前路径, 指定目录不存在会创建文件目录
    shutil.unpack_archive('c_file_name.zip', extra=r'dir_paths', format='zip', )
    
    from datetime import datetime
    # 当前时间
    ctime = datetim.now().strftime('%Y-%m-%d %H:%M:%S')
    # 1.压缩test文件夹
    # 2.放到code目录(默认不存在)
    # 3.将文件解压到/User/henry/Desktop/t中
    

    6.3 json

    序列化:将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化

    目的

    1. 以某种存储形式使自定义对象持久化
      • 对象持久化是指将内存中的对象保存到可永久保存的存储设备中(如磁盘)的一种技术。
    2. 将对象从一个地方传递到另一个地方。
    3. 使程序更具维护性。

    序列化

    • json, 所有语言通用,只能序列化指定的基本数据类型
      • dumps/loads/ dump/load
      • 所有字符串必须都是双引号
      • 最外层只能是dict/list
      • 不能支持load多次
      • dict中key只能是str
    • pickle,几乎支持所有python东西(socket对象),序列化的内容只能用python
      • dumps/loads/ dump/load
      • 支持连续load多次

    1. json

    # 只能包含,int,bool,str,list,dict
    # 最外层必须是list/dict
    # json 中如果包含str,必须是 双引号
    # 如果是tuple类型数据,则会转换为list
    - 特殊的字符串(list和dict嵌套的string)
    - 不同语言间的数据交互
    - 序列化/反序列化:把其语言的数据转化成json格式/ 相反
    
    import json
    v = [12, 3, 4, {'k1': 1}, True, 'adsf']
    # 序列化
    v = json.dumps(v)
    # 反序列化
    json.loads(v)
    
    # 可转为json的数据中包含中文,让中文完全显示
    v = {'k1': 'alex', 'k2': '你好'}
    val = json.dumps(v, ensure_ascii=False)
    print(val, type(val))
    
    val = json.dumps(v)
    print(val, type(val))
    

    2. pickle

    # 使用pickle序列化后,结果是编码后的二进制
    import pickle
    v = {1, 2, 3}
    val = pickle.dumps(v)
    print(val, typ(val))
    val = pickle.loads(v)
    print(val, typ(val))
    # json dump 得到的是str, pickle得到的是bytes
    

    Note(2)

    1. 经过编码过后的数据,通常称为 字节类型/bytes,字符串,格式为:b‘XXXXXXXX'
    2. 压缩后的0101

    6.4 time&datetime

    1. time

    UTC/GMT:世界协调时间

    本地时间:本地时区的时间

    • time.time() # 获取时间戳 1970.1.1 00:00-至今 的秒数
    • time.sleep(10) # 等待的秒数
    • time.timezone # 和标准时间的差距,和电脑的设置有关

    2. datetime

    # 获取datetime格式时间
    from datetime import datetime, timezone, timedelta
    v1 = datetime.now()
    v2 = datetime.utcnow()
    tz = timezone(timedelta(hours = 7))    # 东7区
    v3 = datetime.now(tz)                  # 当前东7区时间
    
    <class 'datetime.datetime'>
    
    # 将datetime格式时间转化为str
    v1 = datetime.now()
    v1.strftime('%Y-%m-%d')                # 连接不能使用汉字(Mac,linux没问题),可以使用.format()方法
    
    # str转datetime,时间加减
    val = datetime.strptime('2019-04-18', '%Y-%m-%d')
    v = val +/- timedelta(days=40)         # 当前时间加/减40天
    
    # 时间戳和datetime关系
    import time, datetime
    ctime = time.time()
    datetime.fromtimestamp(ctime,tz)      # 当前时间,tz和上述相同
    
    v = datetime.now()
    val = v.timestamp()
    print(val)
    

    6.5 模块importlib

    作用:根据字符串形式导入模块

    开放封闭原则:配置文件开放,代码封闭

    1. 使用str导入模块
    2. _import_(和importlib.import_module('模块名'))
    3. os = _import_('os')和2等价
    # 用字符串形式,去对象中找到其成员
    import importlib
    redis = importlib.import_module('utils.redis')
    getattr(redis, 'func')()
    
    import importlib
    path = 'utils.redis.func'
    module_path, func_name = path.rsplit('.', 1)
    getattr(module_path, func_name)()
    
    # 导入模块
    import importlib
    middleware_classes = [
        'utils.redis.Redis',
        'utils.mysql.MySQL',
        'utils.mongo.Mongo'
    ]
    for path in middleware_classes:
        module_path,class_name = path.rsplit('.',maxsplit=1)
        module_object = importlib.import_module(module_path)    # from utils import redis
        cls = getattr(module_object,class_name)
        obj = cls()
        obj.connect()
    
    # 用字符串的形式导入模块。
    # redis = importlib.import_module('utils.redis')
    # 用字符串的形式去对象(模块)找到他的成员。
    # getattr(redis,'func')()
    

    6.6 日志(模块logging)

    日志等级(level) 描述
    DEBUG 最详细的日志信息,典型应用场景是 问题诊断
    INFO 信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作
    WARNING 当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的
    ERROR 由于一个更严重的问题导致某些功能不能正常运行时记录的信息
    CRITICAL 当发生严重错误,导致应用程序不能继续运行时记录的信息

    1. 日志示例

    Note(2)
    • 多次配置logging模块,只有第一次配置有效
    • 在应用日志时,保留堆栈信息需加上exc_info=True
    • 用户:记录日志(银行流水)
    • 程序员:统计、故障排除的 debug、错误完成代码优化
    # 方法1, 
    # basicConfig 不能实现中文编码,不能同时向文件和屏幕输出
    import logging
    # logging.Error 默认级别
    logging.basicConfig(fielname='cmdb.log',
                        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
                        datefmt = '%Y-%m-%d-%H-%M-%S',
                        level=logging.WARNING,)
    logging.log(10, '日志内容')           # 不写
    logging.debug('asdfgh')
    logging.log(30, 'asdfgh')            # 写
    logging.warning('asdfgh')
    

    应用场景:对于异常处理捕获的内容,使用日志模块将其保存到日志

    try:
      requests.get('http://www.google.com')
    except Exception as e:
      msg = str(e)  # 调用e.__str__方法
      logging.error(msg, exc_info=True)   # 线程安全,支持并发
    

    2. logging本质

    # 方法2
    import logging
    # 对象1:文件 + 格式
    file_handler = logging.FileHandler('xxxxx', 'a', encoding='utf-8')
    fmt = logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s')
    file_handler.setFormatter(fmt)
    
    # 对象2:写(封装了对象1 )
    logger = logging.Logger('xxx(在log中会显示)', level=logging.ERROR)
    logger.addHandler(file_handler)
    
    logger.error('你好')
    

    3. 示例

    # 推荐
    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('你好')
    

    logger对像

    1. 创建一个logger对象、文件操作符屏幕操作符格式
    2. 给logger绑定****文件操作和屏幕操作
    3. 给屏幕操作符和文件操作符设置格式
    4. 用logger对象操作
    # warning和error写入不同文件,需要创建不同对象
    import logging
    # 需要加入name参数
    logger = logging.getLogger() 
    fh = logging.FileHandler('log.log') # 写入文件
    sh = logging.StreamHander()  # 不需要参数,输出到屏幕
    logger.addHander(fh)
    logger.addHander(sh)
    # asctime:日志写入时间, name:logger对象名称, levelname:日志级别, module:模块名称
    fmt=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s')
    fh.Setformatter(fmt)
    
    logger.waring('message')
    

    4. 日志切割

    import time
    import logging
    from logging import handlers
    # file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',)
    file_handler = handlers.TimedRotatingFileHandler(filename='x3.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=[file_handler,],
        level=logging.ERROR
    )
    
    for i in range(1,100000):
        time.sleep(1)
        logging.error(str(i))
    	# 在应用日志时,如果想要保留异常的堆栈信息,exc_info=True
        msg = str(e)  # 调用e.__str__方法
        logging.error(msg,exc_info=True)
    

    6.7 collections

    • OrideredDict()
    # dict创建过程
    info = dict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
    
    • defaultDict
    • deque:双端队列
    • namedtuple:默认dict,可以给dict的value设置一个默认值
    from collections import namedtuple
    # 可命名tuple(time 结构化时间)
    # 创建了一个Course类,这个类没有方法,所有属性值不能修改
    Course = namedtuple('Course', ['name',  'price', 'teacher'])
    python = Course('python', 999, 'alex')
    
    print(python)
    print(python.name)
    print(python.price)
    

    6.8 struct模块

    • unpack的结果是元组
    • 第一个参数是数据类型
    # 把数据转换为四个字节
    import struct
    a = struct.pack('i', 1000)				# bytes 类型
    b = struct.pack('i', 78)
    
    a1 = struct.unpack('i', a)
    b1 = struct.unpack('i', b)
    
  • 相关阅读:
    三线程连续打印ABC
    Mybatis知识点总结
    【刷题】LeetCode 292 Nim Game
    Java界面编程-建立一个可以画出图形的简单框架
    第11章 持有对象
    第10章 内部类
    构造器和多态(Chapter8.3)
    对象的创建过程(chapter5.7.3)
    静态数据的初始化(Chapter5.7.2)
    final关键字
  • 原文地址:https://www.cnblogs.com/henryw/p/11681383.html
Copyright © 2011-2022 走看看