• python入门_模块2


    0.collections模块

    在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。

    1.namedtuple: 生成可以使用名字来访问元素内容的tuple

    2.deque: 双端队列,可以快速的从另外一侧追加和推出对象

    3.Counter: 计数器,主要用来计数

    4.OrderedDict: 有序字典

    5.defaultdict: 带有默认值的字典

    # namedtuple 具名元组
    # tuple可以表示不变集合,例如,一个点的二维坐标就可以表示成:
    # 例如:
    from collections import namedtuple
    a = (1,2)
    p = namedtuple('坐标',['x','y'])
    location1 = p(1,2)  # 元素的个数一定要跟上面第二个参数的个数相同
    print(location1)   # 坐标(x=1, y=2)
    print(location1.x)  # 1
    print(location1.y)  # 2
    
    card = namedtuple('扑克牌',['color','number'])
    A = card('','A')  
    print(A)              # 扑克牌(color='♠', number='A')
    print(A.color)     #
    print(A.number)  # A
    # 用具名元组来记录一个城市的信息
    from collections import namedtuple
    City = namedtuple('City', 'name country population coordinates')
    bj = City('BeiJing', 'BJ', 39.9, (116.2317, 39.5427))
    print(bj)
    # City(name='BeiJing', country='BJ', population=39.9, coordinates=(116.2317, 39.5427))
    print(bj.population)
    # 39.9

    deque双端队列

    # 使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。
    
    # deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:
    from collections import deque
    
    q = deque(['s','n','v'])
    # append 和appendleft 分别向2端添加元素
    q.append('1')
    q.appendleft('2')
    print(q) # deque(['2', 's', 'n', 'v', '1'])
    # pop与popleft分别是2端删除元素
    q.pop()
    q.popleft()
    print(q) # deque(['s', 'n', 'v'])

    Counter计数器

    # Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value
    
    from collections import Counter
    
    c = Counter('asdfadghfd_asdf 31242431!')
    print(c)
    # Counter({'d': 4, 'a': 3, 'f': 3, 's': 2, '3': 2, '1': 2, '2': 2, '4': 2, 'g': 1, 'h': 1, '_': 1, ' ': 1, '!': 1})

    OrderedDict: 有序字典

    from collections import OrderedDict
    d = dict([('a',1),('c',2),('b',3),('e',0)])
    print(d)
    # {'a': 1, 'c': 2, 'b': 3, 'e': 0}
    d['z'] = 5
    d['y'] = 6
    print(d)
    # {'a': 1, 'c': 2, 'b': 3, 'e': 0, 'z': 5, 'y': 6}
    print(d.keys())
    # dict_keys(['a', 'c', 'b', 'e', 'z', 'y'])

    defaultdict: 带有默认值的字典

    from collections import defaultdict
    
    # 有下列集合,将所有大于66的值保存至字典的第一个key中,将小于66的值保存在第二个key值中
    # 即: {'k1': 大于66 , 'k2': 小于66}
    ls = [11,22,33,44,55,66,77,88,99]
    my_dict= defaultdict(list)
    for i in ls:
        if i>66:
            my_dict['k1'].append(i)
        else:
            my_dict['k2'].append(i)
    
    print(my_dict())
    # defaultdict(<class 'list'>, {'k2': [11, 22, 33, 44, 55, 66], 'k1': [77, 88, 99]})
    
    # 
    from collections import defaultdict
    dd = defaultdict(lambda: 'N/A')
    dd['key1'] = 'abc'
    dd['key1'] # key1存在
    'abc'
    dd['key2'] # key2不存在,返回默认值
    'N/A'

    一、random模块

    (0, 1):random.random()
    [1, 10]:random.randint(1, 10)
    [1, 10):random.randrange(1, 10)
    (1, 10):random.uniform(1, 10)
    单例集合随机选择1个:random.choice(item)
    单例集合随机选择n个:random.sample(item, n)
    洗牌单列集合:random.shuffle(item)

    import random
    #模块地址
    print(random) # <module 'random' from 'F:\\安装包\\Python36\\lib\\random.py'>
    
    #random.random()取值范围0-1之间的小数,不包含0和1
    for i in range(2):
        print(random.random())  #(0,1)
    #取值0-2之间,但是random.random()输出的值都是0-1之间
    #0.6179348878875671
    #0.7546476092920288
    
    
    #random.randint()  取值范围[1,5]:包含1和5
    for i in range(5):
        print(random.randint(1,5))  #[1,5]
    
    # random.randrange()  #[1,5)取值范围1-4,不包含5
    for i in range(5):
        print(random.randrange(1,5))  #[1,4]
    
    # random.uniform()  取值范围(1,5)之间的小数
    for i in range(5):
        print(random.uniform(1,5))  #小数:(1,5)
    #     print('%.3f' % random.uniform(1,5))  #%f 可以定义取值的长度 %.3f取3位小数
    
    #洗牌单列集合:random.shuffle(item)
    ls = [1,2,3,4,5]
    print(random.shuffle(ls)) #None
    print(ls) #对ls随机排序[4, 5, 2, 3, 1]
    
    #单例集合随机选择1个:random.choice(item)
    print(random.choice(ls))  # 随机输出ls中一个值
    
    #单例集合随机选择n个:random.sample(item, n)
    print(random.sample(ls,3))  # [2, 4, 3]  不会同时出现2个一样的数字
    练习:验证码功能
    # 方法一
    # count验证码位数,根据需求出几位
    import random
    def get_code(count):
        code = ""
        # 能产生大小写字母和数字
        # 进行字符串拼接
        for i in range(count):
            c1 = chr(random.randint(65,90))  #(65,90)  ascii表对应大写字母,chr对应数字转换为字母
            c2 = chr(random.randint(97,122)) #(97,122) ascii表对应小写字母
            c3 = str(random.randint(0,9))    # 数字
    
            code += random.choice([c1,c2,c3])
        return code
    
    print(get_code(4))
    
    # 方法二:效率高,只需要循环2个,但逻辑多
    def get_code(count):
        code = ""
        for i in range(count):
            r = random.choice([1,2 ,3])
            if r == 1:
                c = chr(random.randint(65,90))
            elif r == 2:
                c = chr(random.randint(97,122))
            else:
                c = str(random.randint(0,9))
            code += c
        return code
    
    print(get_code(6)) # d7H7C3
    
    # 第3中方法:将所有字母数字的选项都写在一起,每次选中都不会重复
    def get_code(count):
        target = "1234567890QWERTYUIOPASDFGHJKLZXCVBNMwqertiuopadsfklzvcxbnm"
        code_list = random.sample(target,count)
        return ''.join(code_list) #3PqXiR82
        return code_list  #['p', '1', 'S', '9', 'c', 's', 'k', 'A']
    print(get_code(18))  #Kv47ZiznkPD0eO3I5d

    二、序列化模块

    # 什么是序列化:将对象转化为字符串
    # 什么是反序列化:将字符串转化为对象
    # 为什么要序列化:数据的存储和传输都采用的是字符串类型
    # 序列化的模块:json pickle shelve
    
    # json:支持跨语言,用于数据的传输
    # pickle:支持py的所有数据类型,所有可以将所有py的对象序列化后存储
    # shelve:支持py的所有数据类型,可以即时存与取
    
    # 序列化
    dump
    dumps
    
    # 反序列化
    load
    loads

    三.Json模块:用于传输(多语言支持)

    什么是json:就是完成文本序列化得到的文本字符串,json字符串具有一定的语法规范
    
    1.支持的数据类型:int float str bool dict list null   # json中布尔类型转换为小写,不支持set 和tuple
    2.复杂的json都是由{}与[]嵌套形成的数据
    3.json字符串只能有一个根: json_str = '{}{}' | '{}[]' | '[][]' | '1null'  # 报错,都是两个根
    4.json中的str类型必须用""包裹(json字符串中的字符串类型不支持'' """""")
    import json
    
    # python对象 序列化 json字符串
    data = None
    res = json.dumps(data)
    print(res)
    
    # json字符串 反序列化 python对象
    json_str = '3.14'
    json_str = 'true'
    json_str = 'null'
    json_str = '{}'
    json_str = '[]'
    json_str = '1, null'  # 有误,两个根
    
    json_str = "\"abc\""  #反序列化去引号
    json_str = '"abc"'
    obj = json.loads(json_str)
    print(obj, type(obj))
    操作文件:读()存与写(取)
    #
    序列化 obj = {'name': 'Simon', 'age': 17, 'gender': ''} with open('a.txt', 'w', encoding='utf-8') as wf: json.dump(obj, wf, ensure_ascii=False) # ensure_ascii 默认为True ansci码;#False跟随文件编码utf-8 # json.dump(obj, wf) #{"name": "Simon", "age": 17, "gender": "男"}{"name": "Simon", "age": 17, "gender": "\u7537"} # 文件内容123456:因为wf文件只打开一次,打开的时候操作一次,之后都是写 # wf.write('123') # wf.write('456') # 反序列化 with open('a.txt', 'r', encoding='utf-8') as rf: obj = json.load(rf) print(obj) # {'name': 'Simon', 'age': 17, 'gender': '男'} # 注:json模块的序列化与反序列化是一一对应关系 print(json.load(open('a.txt', 'r', encoding='utf-8'))) # {'name': 'Simon', 'age': 17, 'gender': '男'}

    四、 pickle模块:支持所有数据类型(不支持其他语言,只用于python)

    import pickle
    obj = {'name': 'simon', 'age': 17, 'gender': ''}
    res = pickle.dumps(obj)
    print(res)
    # b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x05\x00\x00\x00simonq\x02X\x03\x00\x00\x00ageq\x03K\x11X\x06\x00\x00\x00genderq\x04X\x03\x00\x00\x00\xe7\x94\xb7q\x05u.'
    
    pickle.dump(obj,open('b.txt','wb'))
    #内容: �}q (X   nameqX   simonqX   ageqKX   genderqX   男qu.
    
    # 反序列化
    print(pickle.loads(res)) # {'name': 'simon', 'age': 17, 'gender': '男'}
    print(pickle.load(open('b.txt', 'rb'))) # {'name': 'simon', 'age': 17, 'gender': '男'}

    五、shelve模块:支持所有数据类型(优化存与取的方式)

    # shelve将dump与load封装为一步
    import shelve
    # 将文件的方法封装到模块中,文件后缀自己随便取的
    #新建了3个文件:c.shv.bak c.shv.dat c.shv.dir
    shv_tool = shelve.open('c.shv')
    
    # 序列化
    # shv_tool['name'] = 'Simon'
    
    # 反序列化
    res = shv_tool['name']
    print(res) # Simon
    
    shv_tool.close()
    # 文件通过shelve对象来关闭,关闭后就不能再取,否则就报错
    
    #  二次操作:重新打开与关闭
    shv_tool = shelve.open('c.shv')
    print(shv_tool['name']) # Simon
    shv_tool.close()
    
    # 操作方式
    with shelve.open('c.shv') as shv_tool:
        print(shv_tool['name']) # Simon
    
    # writeback将反序列化到内存的数据,操作后即时同步到文件中
    with shelve.open('c.shv', writeback=True) as shv_tool:
        shv_tool['stus'] = ['Bob', 'Tom']  # 重置
        # print(shv_tool['stus'])  # ['Bob', 'Tom']
    
        shv_tool['stus'].append('Jobs')  #  将数据取到内存,在内存中添加
        print(shv_tool['stus']) # ['Bob', 'Tom', 'Jobs']

    六、shutil:可以操作权限的处理文件模块

    import shutil
    
    # 基于路径的文件复制:
    shutil.copyfile('source_file', 'target_file')
    # 绝对路径:复制后的文件名是需要的
    shutil.copyfile(r'C:\shelev.py',r'D:\target.py')
    
    # 基于流的文件复制:
    with open('source_file', 'rb') as r, open('target_file', 'wb') as w:
        shutil.copyfileobj(r, w)
        
    # 递归删除目标目录:目录里有文件也直接删除
    shutil.rmtree('target_folder')
    
    # 文件移动
    shutil.remove('old_file', 'new_file')
    
    # 文件夹压缩
    # file_name: 压缩后得到的文件名  format:压缩格式  archive_path:要压缩的文件夹路径
    shutil.make_archive('file_name', 'format', 'archive_path')
    # 举例
    shutil.make_archive('target/abc', 'zip', 'source') #在target 目录中将source目录压缩到target目录中名为abc.zip
    
    # 文件夹解压
    # unpack_file: 解压的文件  unpack_name:解压得到的文件夹名  format:解压格式
    shutil.unpack_archive('unpack_file', 'unpack_name', 'format')
    # 举例
    shutil.unpack_archive('target/abc.zip', 'target/xyz', 'zip') #将abc.zip解压为xyz文件夹

     七、加密模块

    # 一般加密解密方法:
    # md5加密:不可逆加密
    # 碰撞解密:用数据再进行一次加密,与原加密结果做匹配

    hashlib模块加密

    import hashlib
    
    data = '数据'  # 生成对象
    lock_obj = hashlib.md5(data.encode('utf-8'))  # 生产加密锁对象,传入加密数据
    result = lock_obj.hexdigest()  # 获取加密后的加密串
    print(result)
    
    # update可以往锁对象中添加加密数据
    lock_obj = hashlib.md5()
    lock_obj.update(b'123')
    lock_obj.update(b'abc')
    lock_obj.update('嘿嘿'.encode('utf-8'))
    print(lock_obj.hexdigest())
    
    lock_obj.update(b'000')
    print(lock_obj.hexdigest())  # 000 | '123abc嘿嘿000'.encode('utf-8')
    
    print(hashlib.md5('123abc嘿嘿000'.encode('utf-8')).hexdigest())
    # 注:要为新数据提供加密,一定要为该数据创建一个加密对象
    # 加盐:前提是支持update
    # 什么是加盐:在原数据前或后添加一些预定的数据,与原数据一起进行加密
    # 为什么要加盐:
    # 1.当原数据过于简单,可以对其加盐,提高数据的复杂度
    # 2.盐与数据有一定相似度,混淆对真实数据的提取
    
    data = 'ab_12'
    lock_obj = hashlib.md5()
    lock_obj.update(b'a12_d')
    lock_obj.update(data.encode('utf-8'))
    lock_obj.update(b'dd_121')
    print(lock_obj.hexdigest())
    # a12_dab_12dd_121在数据前后加盐混淆
    
    # 其他位数加密
    lock_obj = hashlib.sha3_256(b'123')
    print(lock_obj.hexdigest())
    lock_obj = hashlib.sha3_512(b'123')
    lock_obj.update(b'salt')
    print(lock_obj.hexdigest())

    hmac模块加密

    import hmac
    # 与hashlib的不同点:生产锁对象时必须提高数据参数
    lock_obj = hmac.new(b'')
    print(lock_obj.hexdigest())
    
    # 支持加盐 lock_obj
    = hmac.new(b'') lock_obj.update(b'salt') print(lock_obj.hexdigest())

     八、logging:日志模块

    # logging记录项目日志的模块
    # 记录日志:将项目中产生的一些数据,或是信息,或是错误不再输出到控制台,而是输出到文件中,保存这样信息的文件就称之为日志文件
    # 日志级别
    在开始记录日志前还需要明确,日志的级别
    
    随着时间的推移,日志记录会非常多,成千上万行,如何快速找到需要的日志记录这就成了问题
    
    解决的方案就是 给日志划分级别
    logging模块将日志分为了五个级别,从高到低分别是:
    1.info 常规信息
    2.debug 调试信息
    3.warning 警告信息(默认级别)
    4.error 错误信息
    5.cretical 严重错误
    
    本质上他们使用数字来表示级别的,从高到低分别是10,20,30,40,50
    #1.导入模块
    import logging
    
    #2.输出日志
    logging.info("info")
    logging.debug("debug调试")
    logging.warning("warning警告")
    logging.error("error错误")
    logging.critical("critical严重错误")
    
    # 输出 WARNING:root:warning
    # 输出 ERROR:root:error
    # 输出 CRITICAL:root:critical

    1.logging模块的基本配置使用:

    import logging
    import sys
    
    # 2.日志的基本配置
    logging.basicConfig(
        # 输出级别
        level=logging.INFO,
        # level=10,
    
        # 输出位置
        # stream=sys.stderr,  # sys.stdout  往控制台输出
        filename='log/my.log',  # 往文件输出  => 如果需要同时往多个位置输出,需要handles
    
        # 输出格式
        format='%(asctime)s[%(name)s]: %(msg)s',
        datefmt='%Y-%m-%d %H:%M:%S'
    )
    # my.log日志:2019-05-16 14:39:32[root]: error msg
    # 标准输入 # print(sys.stdin.readline())

    # filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
    # filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
    # format:指定handler使用的日志显示格式。 
    # datefmt:指定日期时间格式。 
    # level:设置rootlogger(后边会讲解具体概念)的日志级别 
    
    #案例:
    logging.basicConfig(
        filename="aaa.log",
        filemode="at",
        datefmt="%Y-%m-%d %H:%M:%S %p",
        format="%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s",
        level=10
    )

    格式化全部可用名称:

    %(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:用户输出的消息

    2.logging的成员组成

     

    logging模块的四个核心角色:
    1.Logger   日志生成器 产生日志
    2.Filter    日志过滤器  过滤日志
    3.Handler 日志处理器 对日志进行格式化,并输出到指定位置(控制台或文件)
    4.Formater 处理日志的格式
    import logging
    
    # 1.打印者:自定义的打印者如何配置
    log1 = logging.getLogger('logger name')
    
    # 2.输出位置:两个文件输出位置与一个控制台输出位置
    hd_a = logging.FileHandler('log/a.log', encoding='utf-8')
    hd_cmd = logging.StreamHandler()
    
    # 3.输出格式
    fmt1 = logging.Formatter('%(asctime)s 【%(name)s】- %(msg)s')
    fmt2 = logging.Formatter('%(asctime)s - %(msg)s')
    
    # 4.打印者添加句柄 - 设置打印者的输出位置
    log1.addHandler(hd_a)
    log1.addHandler(hd_cmd)
    
    # 5.将格式绑定给输出位置(句柄)
    hd_a.setFormatter(fmt1)
    hd_cmd.setFormatter(fmt2)
    
    # 6.权限控制
    log1.setLevel(logging.DEBUG)  # 打印者规定打印级别
    hd_a.setLevel(logging.WARNING)  # 不同输出位置(句柄)再可以二次限定输出级别
    hd_cmd.setLevel(logging.DEBUG)  # 不同输出位置(句柄)再可以二次限定输出级别
    
    # 7.不同级别输出信息
    log1.debug('debug msg')
    log1.info('info msg')
    log1.warning('warning msg')
    log1.error('error msg')
    log1.critical('critical msg')
    import logging
    # root打印者,用logging.basicConfig来配置
    # logging.critical('12345')
    
    # 1.打印者:自定义的打印者如何配置
    log1 = logging.getLogger('Owen')
    # log1.critical('67890')
    
    log2 = logging.getLogger('Simon')
    # log2.critical('00000')
    
    # 2.输出位置:两个文件输出位置与一个控制台输出位置
    hd_a = logging.FileHandler('log/a.log', encoding='utf-8')
    hd_b = logging.FileHandler('log/b.log', encoding='utf-8')
    hd_cmd = logging.StreamHandler()  #控制台输出
    
    # )) 为输出者绑定输出位置
    log1.addHandler(hd_a)
    log1.addHandler(hd_b)
    
    log2.addHandler(hd_b)
    log2.addHandler(hd_cmd)
    
    # 3.输出格式
    fmt1 = logging.Formatter('%(asctime)s 【%(name)s】- %(msg)s')
    fmt2 = logging.Formatter('%(asctime)s - %(msg)s')
    
    # ))将格式绑定给输出位置(句柄)
    hd_a.setFormatter(fmt1)
    hd_b.setFormatter(fmt1)
    hd_cmd.setFormatter(fmt2)
    
    # 级别控制: 打印者规定打印级别,输出位置(句柄)再可以二次限定,级别>=打印者级别
    log2.setLevel(logging.DEBUG)
    hd_b.setLevel(logging.WARNING)
    hd_cmd.setLevel(logging.DEBUG)
    
    log2.debug('debug msg')
    log2.info('info msg')
    log2.warning('warning msg')
    log2.error('error msg')
    log2.critical('critical msg')
    
    # 4.输出
    log1.critical('log1 输出的 critical msg')
    log2.critical('log2 输出的 critical msg')
    
    # 过滤:少用
    # logging.Filter
    多日志多级别输出

     3.logging配置文件项目开发运用

    # 1.将打印者,句柄,与格式封装成配置信息
    # 2.加载配置信息
    # 3.使用自定义logger,采用的就是配置信息设置的logger
    
    # 优势:1,2两步是一劳永逸的,后期开发只需要在要记录日志的文件中使用自定义logger
    # 一、基础配置:目录conf/setting.py
    LOGGING_DIC = {
        'version': 1,
        'disable_existing_loggers': False, #让系统的默认配置失效
        'formatters': {
            # 名称格式定义
            'o_fmt1': {
                'format': '%(asctime)s 【%(name)s】- %(msg)s'
            },
            'o_fmt2': {
                'format': '%(asctime)s - %(msg)s'
            }
        },
        'filters': {},
        'handlers': {
            'o_hd_file': {
                'level': 'WARNING',
                'class': 'logging.handlers.RotatingFileHandler',  # 打印到控制台
                'formatter': 'o_fmt1',
                'filename': 'log/sys.log',
                'encoding': 'utf-8',
                'maxBytes': 1024*1024*5,  # 日志大小5M
                'backupCount': 5,   # 文件切分:写满一个就改名为sys1.log,写满5个清空重新记录
            },
            'o_hd_cmd': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',  # 打印到控制台
                'formatter': 'o_fmt2'
            }
        },
        'loggers': {
            'o_owen': {
                'level': 'DEBUG',
                'handlers': ['o_hd_file', 'o_hd_cmd']
            },
            'o_simon': {
                'level': 'DEBUG',
                'handlers': ['o_hd_cmd'],
                # 'propagate': True  # 向更高的level logging传递
            }
        }
    }
    
    # 二、加载配置
    import logging.config
    logging.config.dictConfig(LOGGING_DIC)
    
    
    # 三、使用
    log = logging.getLogger('o_simon')
    log.critical('信息')
    
    log1 = logging.getLogger('o_owen')
    log1.critical('信息')

    # 目录:lib/common.py
    from conf.settings import LOGGING_DIC
    import logging.config
    logging.config.dictConfig(LOGGING_DIC)
    
    def getLogger(name):
        return logging.getLogger(name)
    测试:
    from lib.common import getLogger
    log = getLogger('o_owen')
    
    log.debug('12345')
    log.critical('67890')
    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'
    
    id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
    logfile_path = "配置文件路径"
    
    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',  # 日志文件的编码
            },
        },
        'loggers': {
            #logging.getLogger(__name__)拿到的logger配置
            'aa': {
                'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
                'level': 'DEBUG',
                'propagate': True,  # 向上(更高level的logger)传递
            },
            # 把key设置为空
            '': {
                'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
                'level': 'DEBUG',
                'propagate': True,  # 向上(更高level的logger)传递
            },
        },
    }
    标准代码
    #lib/common.py
    #日志功能
    import logging.config
    from conf import settings
    
    # 在lib 文件夹的common文件中生成日志对象
    #生成日志对象
    def get_logger(name):
        # 先把日志配置传给logging
        logging.config.dictConfig(settings.LOGGING_DIC)
        # 生产日志对象--》接收的是name,根据name打印相应的日志
        my_logger = logging.getLogger(name)
        return my_logger
    
    
    # conf/settings.py
    import os
    
    # test目录
    BASE_PATH = os.path.dirname(os.path.dirname(__file__))
    # test/db目录
    DB_PATH = os.path.join(BASE_PATH, 'db')
    
    
    # 日志配置文件
    '''
    logging 配置
    '''
    import os
    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'
    
    id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
    
    # 日志目录
    LOG_PATH = os.path.join(BASE_PATH,'log')
    log_filename = 'Atm_Shop.log'
    
    if not os.path.isdir(LOG_PATH):
        os.mkdir(LOG_PATH)
    
    # log文件全路径
    logfile_path = os.path.join(LOG_PATH,log_filename)
    
    
    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',  # 日志文件的编码
            },
        },
        'loggers': {
            #logging.getLogger(__name__)拿到的logger配置
            'aa': {
                'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
                'level': 'DEBUG',
                'propagate': True,  # 向上(更高level的logger)传递
            },
            # 把key设置为空
            '': {
                'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
                'level': 'DEBUG',
                'propagate': True,  # 向上(更高level的logger)传递
            },
        },
    }
    
    
    # 引用
    from lib import common
    # 获取银行日志功能
    bank_log = common.get_logger('bank')
    
    bank_log.info('%s提现%s元成功,手续费为%s' % (user, money2,money3))
    标准代码2

    九、re模块

    # re:正则,全称正则字符串 - re就是有特殊语法的字符串
    # re可以将有正则语法的字符串解析为对应的正则对象,用来匹配目标字符串
    
    # 学习re的目的:1.判断目标字符串是否合法 2.在目标字符串中提取想要的信息(信息匹配规则采用正则)
    import re
    
    # 从123abc123中查找1
    r1 = re.findall(r'1', '123abc123')
    print(r1) # ['1', '1']
    
    r2 = re.findall(r'a', '123abc123ABC', flags=re.I) # re.I 不区分大小写匹配
    print(r2) # ['a', 'A']
    
    # 1.将 r'\d' 丢给_compile得到可以匹配数字的 正则对象
    # 2.正则对象.findall('目标字符串')
    r3 = re.findall(r'\d', '123abc123')
    print(r3) # ['1', '2', '3', '1', '2', '3']
    
    re_obj = re.compile(r'\d')  # 将 r'\d' 丢给_compile得到可以匹配数字的 正则对象
    r4 = re_obj.findall('123abc123')  # 正则对象.findall('目标字符串')
    print(r4) # ['1', '2', '3', '1', '2', '3']

    正则语法

    单个字符语法:

    import re
    
    # 一、单个字符语法
    # 匹配a
    print(re.findall(r'a', '123abc嘿嘿'))  # ['a']
    
    # a或b
    print(re.findall(r'a|b', '123abc嘿嘿'))  # ['a', 'b'] 不建议使用
    print(re.findall(r'[ab]', '123abc嘿嘿'))  # ['a', 'b'] 建议使用
    
    # 非a非b
    print(re.findall(r'[^ab]', '123abc嘿嘿'))  # ['1', '2', '3', 'c', '嘿', '嘿']
    
    # 数字
    print(re.findall(r'[0-9]', '12abc嘿嘿12'))  # ['1', '2', '1', '2'] 建议使用
    print(re.findall(r'\d', '12abc嘿嘿12'))  # ['1', '2', '1', '2'] 不建议使用
    
    # 字母
    print(re.findall(r'[a-zA-Z]', '12abc[嘿嘿ABC'))  # ['a', 'b', 'c', 'A', 'B', 'C']
    
    # 字母数字_常用汉字:\w => 建议使用 [a-zA-Z0-9_]
    print(re.findall(r'\w', '12abc[_嘿嘿ABC'))  # ['1', '2', 'a', 'b', 'c', '_', '嘿', '嘿', 'A', 'B', 'C']
    
    # 汉字 [\u4e00-\u9fa5]代表汉字
    print(re.findall(r'[\u4e00-\u9fa5]', '12abc[_嘿嘿ABC'))  # ['嘿', '嘿']
    
    # 空白字符:\s => 建议使用[ \f\n\r\t\v]
    print(re.findall(r'\s', ' \f\n\r\t\v'))  # [' ', '\x0c', '\n', '\r', '\t', '\x0b']
    
    # 非\n的任意字符: .
    print(re.findall(r'.', ' \f\n\r\t\v*&_.'))  # [' ', '\x0c', '\r', '\t', '\x0b', '*', '&', '_', '.']
    
    # 只想匹配.字符:\.
    print(re.findall(r'\.', ' \f\n\r\t\v*&_.'))  # ['.']
    
    # re.S: 让.也能匹配\n,就可以理解为 . 可以匹配所有字符
    print(re.findall(r'.', ' \f\n\r\t\v*&_.', flags=re.S))
    
    # 取对立面 \d数字 \D非数字  \w=>\W  \s=>\S
    print(re.findall(r'\D', '12abc\f嘿嘿12'))  # ['a', 'b', 'c', '\x0c', '嘿', '嘿']

     重复字符语法:

    print(re.findall(r'ab', 'abacbabc'))  # ['ab', 'ab']
    
    # 指定个数: 匹配abb
    print(re.findall(r'ab{2}', 'aababbabbb'))  # ['abb', 'abb']
    
    # 贪婪匹配: 尽可能多的匹配
    # a0~2个b: a | ab | abb
    print(re.findall(r'ab{,2}', 'aababbabbb'))  # ['a', 'ab', 'abb', 'abb']
    
    # a0~n个b:
    print(re.findall(r'ab{0,}', 'aababbabbb'))  # ['a', 'ab', 'abb', 'abbb']
    
    # a1~3个b:
    print(re.findall(r'ab{1,3}', 'aababbabbb'))  # ['ab', 'abb', 'abbb']
    
    # *: {0,}
    print(re.findall(r'ab*', 'aababbabbb'))  # ['a', 'ab', 'abb', 'abbb']
    # +: {1,}
    print(re.findall(r'ab+', 'aababbabbb'))  # ['ab', 'abb', 'abbb']
    # ?: {,1}
    print(re.findall(r'ab?', 'aababbabbb'))  # ['a', 'ab', 'ab', 'ab']
    
    # 非贪婪匹配
    print(re.findall(r'ab{1,3}?', 'aababbabbb'))  # ['ab', 'ab', 'ab']
    
    # 重点:非贪婪匹配应用场景,一般都是结合有开头与结尾的标识
    print(re.findall(r'<.{1,}>', '<a><b>msg</b></a>'))  # ['<a><b>msg</b></a>']
    # 匹配标签
    print(re.findall(r'<.{1,}?>', '<a><b>msg</b></a>'))  # ['<a>', '<b>', '</b>', '</a>']
    
    # *?: {0,}?
    # +?: {1,}?
    # ??: {,1}?
    print(re.findall(r'<.+?>', '<a><b>msg</b></a>'))  # ['<a>', '<b>', '</b>', '</a>']

     分组语法:

    # 引子
    print(re.findall(r'(?:ab){2}', 'abbabab'))  # ['abab']
    
    # findall(): 没有分组情况下,显示匹配的结果;如果有分组,显示分组结果
    
    # 分组:()
    # 取消分组:(?:)
    # 有名分组:(?P<名字>)
    
    # 案例:
    # 匹配链接
    print(re.findall(r'www\..+?\.com', 'www.baidu.comabcwww.sina.com'))  # ['www.baidu.com', 'www.sina.com']
    # 获取链接的域名:['baidu', 'sina']
    print(re.findall(r'www\.(.+?)\.com', 'www.baidu.comabcwww.sina.com'))  # ['baidu', 'sina']
    
    # 分组编号: 从左往右数左(进行分组编号
    # [('www.baidu.com', 'baidu', 'com'), ('www.sina.edu', 'sina', 'edu')]
    res = re.findall(r'(www\.(.+?)\.(com|edu))', 'www.baidu.comabcwww.sina.edu')
    print(res)
    print(res[0][1])
    
    # 取消分组:(?:) 应用于,要将一些数据作为整体看待,但由不能产生分组
    # [('www.baidu.com', 'baidu'), ('www.sina.edu', 'sina')]
    res = re.findall(r'(www\.(.+?)\.(?:com|edu))', 'www.baidu.comabcwww.sina.edu')
    print(res)

    其他正则方法的使用:

    # match:不是全文匹配,必须从头开始匹配,且只匹配一次
    res = re.match(r'(www\.(?P<site_name>.+?)\.(?:com|edu))', 'www.baidu.comwww.sina.edu')
    # 可以通过分组号直接取出分组内容
    print(res.group(1))
    print(res.group(2))
    # print(res.group(0), res)  # 匹配的整体
    
    # 有名分组
    print(res.group('site_name'))
    
    # split(): 拆分
    print('abc def xyz'.split(' '))
    print(re.split(r' ', 'abc def xyz'))
    print(re.split(r'[,@ ]', 'abc,def@xyz opq'))
    
    
    # sub(): 替换
    res = re.sub(r'good', 'bed', 'good good day a')
    print(res)  # bed bed day a
    
    res = re.sub(r'good', 'bed', 'good good day a', count=1)
    print(res)  # bed good day a
    
    res = re.sub(r'good day a', '123', 'good day a!!!')
    print(res)  # 123!!!
    
    # 结合分组可以完成数据的重组
    res = re.sub(r'(good) (day) (a)', r'today is \3 \1 \2', 'good day a!!!')
    print(res)  # today is a good day!!!
    元字符描述
    \ 将下一个字符标记符、或一个向后引用、或一个八进制转义符。例如,“\n”匹配\n。“\n”匹配换行符。序列“\”匹配“\”而“(”则匹配“(”。即相当于多种编程语言中都有的“转义字符”的概念。
    ^ 匹配输入字行首。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
    $ 匹配输入行尾。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
    * 匹配前面的子表达式任意次。例如,zo能匹配“z”,也能匹配“zo”以及“zoo”。等价于{0,}。
    + 匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
    {n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
    {n,} n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
    {n,m} mn均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
    ? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”。?等价于{0,1}。
    ? 当该字符紧跟在任何一个其他限制符(,+,?,{n},{n,},{n,m*})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 ['o', 'o', 'o', 'o']
    .点 匹配除“\n”和"\r"之外的任何单个字符。要匹配包括“\n”和"\r"在内的任何字符,请使用像“[\s\S]”的模式。
       
    x|y 匹配x或y。例如,“z|food”能匹配“z”或“food”(此处请谨慎)。“[zf]ood”则匹配“zood”或“food”。
    [xyz] 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
    [^xyz] 负值字符集合。匹配未包含的任意字符。例如,“abc”可以匹配“plain”中的“plin”任一字符。
    [a-z] 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.
    [^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,“a-z”可以匹配任何不在“a”到“z”范围内的任意字符。
    \b 匹配一个单词的边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”;“\b1”可以匹配“1_23”中的“1”,但不能匹配“21_3”中的“1_”。
    \B 匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”
    \s 匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
    \S 匹配任何可见字符。等价于 \f\n\r\t\v
    \w 匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。
    \W 匹配任何非单词字符。等价于“A-Za-z0-9_”。
    \d 匹配一个数字字符。等价于[0-9]。grep 要加上-P,perl正则支持
    \D 匹配一个非数字字符。等价于0-9。grep要加上-P,perl正则支持
    \n 匹配一个换行符。等价于\x0a和\cJ。
    \r 匹配一个回车符。等价于\x0d和\cM。
    \t 匹配一个制表符。等价于\x09和\cI。
    ( ) 将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。
    (?:pattern) 非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
    | 将两个匹配条件进行逻辑“或”(Or)运算。例如正则表达式(him|her) 匹配"it belongs to him"和"it belongs to her",但是不能匹配"it belongs to them."。注意:这个元字符不是所有的软件都支持的。

    十、shell脚本之subprocess模块

    #Popen
    order = subprocess.Popen('dir',
    shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
    )

    res = order.stdout.read().decode('gbk')
    print(res)

    print('==============================')

    res = order.stderr.read().decode('gbk')
    print(res)
    # 举例
    # windows下测试列出目录文件
    # run
    import subprocess
    order = subprocess.run('dir',
    shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
    )

    res = order.stdout.decode('gbk')
    print(res)

    print('==============================')
    # stderr 输出错误
    res = order.stderr.decode('gbk')
    print(res)
    #Centos系统
    >>> a = subprocess.call(['df','-lh'],shell=False)
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/vda1        40G  9.0G   29G  25% /
    /dev/vdb         99G   16G   78G  18% /db
    tmpfs           783M     0  783M   0% /run/user/1000
    
    >>> r1=subprocess.getstatusoutput("dir")
    >>> r1
    (0, 'lova  test.sh')
    
    >>> r2 = subprocess.Popen('ping -c2 www.baidu.com',shell=True)
    >>> PING www.a.shifen.com (115.239.210.27) 56(84) bytes of data.
    64 bytes from 115.239.210.27 (115.239.210.27): icmp_seq=1 ttl=54 time=8.59 ms
    64 bytes from 115.239.210.27 (115.239.210.27): icmp_seq=2 ttl=54 time=8.64 ms
    
    --- www.a.shifen.com ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 3004ms
    rtt min/avg/max/mdev = 8.595/8.621/8.648/0.094 ms
    
    >>> subprocess.Popen('./test.sh',shell=True)
    <subprocess.Popen object at 0x7f2c51f10160>
    >>> Hello World!
    
    >>> res = subprocess.Popen('./test.sh',stdout = subprocess.PIPE,shell=True,stderr=subprocess.PIPE)
    >>> res1 = res.stdout.read()
    >>> res1
    b'Hello World!\n'
    >>> print(res1)
    b'Hello World!\n'
    def subrun(cmd):
        comply = subprocess.Popen(cmd,
                                  shell=True,
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE,
                                  )
        res_stdout = comply.stdout.read()
        res_stderr = comply.stderr.read()
        if res_stdout:
            return res_stdout.decode('utf-8')
        return res_stderr.decode('utf-8')
    函数传参

    十二、configparser 模块

    # my.ini 配置文件读写
    """
    [server]
    ip = 192.168.66.88
    port = 3306
    
    [client]
    user = root
    password = root
    """
    
    import configparser
    
    # 1.初始化
    parser = configparser.ConfigParser()
    
    # 2.读
    parser.read('my.ini', encoding='utf-8')
    # section | option | value
    # 读取列表
    sts = parser.sections()
    print(sts, type(sts))  # ['server', 'client'] <class 'list'>
    
    ops = parser.options(sts[0])
    print(ops)  # ['ip', 'port']
    value = parser.get(sts[0], ops[0])
    print(value, type(value))  # 192.168.66.88 <class 'str'>
    # # get=>str getboolean=>bool getfloat=>float getint=>int
    print(parser.get('server', 'port')) # 3306
    
    # 3.写
    parser.read('my.ini', encoding='utf-8')
    parser.set('server', 'port', '6666')
    parser.write(open('my.ini', 'w'))

    十三、xml模块

    # xml文件:1.作为传输文件用于数据的传输  2.作为配置文件配置信息
    
    # 1.只能由一个根标签
    # 2.所有的标签都是自定义的
    # 3.标签名就是key,标签的内容就是value
    # 4.与json不同的是,标签不仅可以有key和value,还有标签的属性
    # 注:xml的属性通常用来表示标签间的区分度,用于解析xml来使用
    <data>
        <country name="Liechtenstein">
            <rank updated="yes">2</rank>
            <year>2008</year>
            <gdppc>141100</gdppc>
            <neighbor direction="E" name="Austria" />
            <neighbor direction="W" name="Switzerland" />
        </country>
        <country name="Singapore">
            <rank updated="yes">5</rank>
            <year>2011</year>
            <gdppc>88888</gdppc>
            <neighbor direction="N" name="Malaysia" />
        </country>
        <country name="Panama">
            <rank updated="yes">69</rank>
            <year>2011</year>
            <gdppc>13600</gdppc>
            <neighbor direction="W" name="Costa Rica" />
            <neighbor direction="E" name="Colombia" />
        </country>
    </data>
    my.xml
    """
    {"countrys": [
        {
            "rank": 2,
            "year": 2008,
            "gdppc": 141100
        },
        {},
        {}
    ]}
    
    {
        "data": {
            "countrys": [
                {},
                {},
                {}
            ]
        }
    }
    """
    # xml的文件解析 => 将xml转化为json类型的数据
    # dict list => json
    
    import xml.etree.ElementTree as ET
    
    # 读文件
    tree = ET.parse("my.xml")
    print(tree)  # xml.etree.ElementTree.ElementTree # <xml.etree.ElementTree.ElementTree object at 0x0000000001EACA58>
    # 根节点
    root_ele = tree.getroot()
    print(root_ele)  # Element 'data':<Element 'data' at 0x0000000001DBD4A8>
    
    # 遍历往下
    # print(root_ele[1])
    for ele in root_ele:
        print(ele, ele.attrib)
        if ele.attrib['name'] == 'Singapore':
            for e in ele:
                print(e, e.tag)
                if e.tag == 'gdppc':
                    print(e.text)
                    e.text = '6666'  # 只修改了内容
    
    # 全文搜索指定名的子标签
    # ele.iter("标签名")
    # 非全文查找满足条件的第一个子标签
    # ele.find("标签名")
    # 非全文查找满足条件的所有子标签
    # ele.findall("标签名")
    # print('==============')
    # cs = root_ele.iter('country')
    # for c in cs:
    #     print(c)
    # print('==============')
    # print(root_ele.find('country').attrib) # {'name': 'Liechtenstein'}
    # print(root_ele.find('rank').attrib)  # 不能跨标签取,只能取子标签
    # print('==============')
    # print(root_ele.findall('country'))
    
    # 将内存的数据重新写入文件
    tree.write("my.xml")

    # 读
    data = {'countrys': []}
    tree = ET.parse("my.xml")
    root = tree.getroot()
    for ele in root:
    country = {}
    for e in ele:
    if e.text and e.text.strip():
    country[e.tag] = e.text
    data['countrys'].append(country)
    print(data)

    十四、Excel操作

    # Excel
                                年终报表                
                  教学部    市场部    咨询部    总计
    Jan-19    10    15            5        30
    Feb-19    11    20            5        36
    Mar-19    12    25            5        42
    Apr-19    13    30            5        48
    May-19    14    35            5        54
    Jun-19    15    40            5        60
    Jul-19    16    45            5        66
    Aug-19    17    50            5        72
    Sep-19    18    55            5        78
    Oct-19    19    60            5        84
    Nov-19    20    65            5        90
    Dec-19    21    70            5        96

    基本操作

    imimport xlrd
    
    # 读取文件
    work_book = xlrd.open_workbook("my.xlsx")
    # 获取所有所有表格名称
    print(work_book.sheet_names())
    # 选取一个表
    sheet = work_book.sheet_by_index(0)
    # 表格名称
    print(sheet.name)
    # 行数
    print(sheet.nrows)
    # 列数
    print(sheet.ncols)
    # 某行全部
    print(sheet.row(6))
    print(sheet.row(13))
    # 某列全部
    print(sheet.col(4))
    # 某行列区间
    print(sheet.row_slice(6, start_colx=0, end_colx=4))
    # 某列行区间
    print(sheet.col_slice(3, start_rowx=0, end_rowx=3))
    # 某行类型0:空 1:str 2:num 3:date | 值
    print(sheet.row_types(1), sheet.row_values(6))
    
    # 单元格
    print(sheet.cell(6,0).value) # 取值
    print(sheet.cell(6,0).ctype) # 取类型
    print(sheet.cell_value(6,0)) # 直接取值
    print(sheet.cell_type(6,0)) # 直接取类型
    
    # 0:以1900年为基准 1:以1904年为基准
    print(xlrd.xldate_as_datetime(sheet.cell(6, 0).value, 0))
    import xlwt
    # 创建工作簿
    work = xlwt.Workbook()
    # 创建一个表
    sheet = work.add_sheet("员工信息数据")
    # 创建一个字体对象
    # font = xlwt.Font()
    # font.name = "Times New Roman"  # 字体名称
    # font.bold = True  # 加粗
    # font.italic = True  # 斜体
    # font.underline = True  # 下划线
    # 创建一个样式对象
    # style = xlwt.XFStyle()
    # style.font = font
    keys = ['Owen', 'Zero', 'Egon', 'Liuxx', 'Yhh']
    # 写入标题
    c = 0
    for k in keys:
        # sheet.write(0, keys.index(k), k, style)
        # sheet.write(0, keys.index(k), k)
    
        sheet.write(keys.index(k) + 5, 2, k if k != 'Egon' else 'cool')
        # sheet.write(c, c, k)
        # c += 1
    
    # 写入数据
    # sheet.write(1, 0, 'cool', style)
    # sheet.write(0, 0, 'cool')
    # 保存至文件
    work.save("new_my.xls")
  • 相关阅读:
    Emit介绍【转】
    在.NET中使用反射实现简易插件机制【转】
    RabbitMQ笔记-Qos与消息应答
    Http级别缓存助手类(ASP.Net Core)
    实现一个迷你IOC容器
    使用CMake在Windows环境下的VS2019中配置openCV
    如何在Visual Studio 2019中启动并配置一个使用pyTorch的C++项目(Windows系统,CMAKE项目)
    windows环境下使用python中tensorflow的tensorboard功能无法创建指定路径的问题
    使用python的selenium库自动填写网页(疫情每日一报)
    十进制转换二进制toBinaryString源码分析
  • 原文地址:https://www.cnblogs.com/yangmeichong/p/10873920.html
Copyright © 2020-2023  润新知