• python模块简述


    time模块

    import time
    print(time.time())#获取时间戳 浮点数
    print(time.sleep(2))#睡眠,阻塞
    print(time.strftime('%Y-%m-%d %H:%M:%S'))#时间显示格式,页面显示的格式
    print(time.gmtime())#结构化时间,元祖的形式(命名元祖),可以根据索引和元素进行查找
    time.struct_time(tm_year=2019, tm_mon=7, tm_mday=25, tm_hour=8, tm_min=10, tm_sec=50, tm_wday=3, tm_yday=206, tm_isdst=0)
    #time.localtime获取的是当地时间
    	# print(time.gmtime()[0])
    	# print(time.gmtime().tm_year)
    #将时间戳转换成字符串时间
    print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime(1564028611.631374)))
    #将字符串时间转换成时间戳
    print(time.mktime(time.strptime("2024-3-16 12:30:30","%Y-%m-%d %H:%M:%S")))
    ---------------------------------------
    重点:
    # time重点:
    time.time()
    time.sleep() 
    time.gmtime() / time.localtime() #
    time.strftime("格式化","结构化时间") #
    time.strptime("字符串","格式化")
    time.mktime()
    ****************************************************************
    

    datatime模块

    print(type(datetime.now()))获取当前时间,获取的是一个对象
    print(datetime(2019,5,21,15,14,00) - datetime(2019,5,20,14,20,00))计算时间差
    # 将当前时间转化成时间戳
    t = datetime.now()
    print(t.timestamp())
    -----------------------------------------
    # 将时间戳转化成当前时间
    import time
    print(datetime.fromtimestamp(15000000000))
    -----------------------------------------------------
    # 将字符串转成对象
    print(type(datetime.strptime("2019-10-10 22:23:24","%Y-%m-%d %H:%M:%S")))
    -----------------------------------------------------
    # 将对象转成字符串
    print(str(datetime.now()))
    print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
    ------------------------------------------------------
    # datetime加减
    print(datetime.now() + timedelta(hours=30 * 24 * 12))
    print(datetime.now() - timedelta(hours=30 * 24 * 12))
    ***********************************************************
    # datatime模块
    import datetime
    now_time = datetime.datetime.now()  # 现在的时间
    # 只能调整的字段:weeks days hours minutes seconds
    print(datetime.datetime.now() + datetime.timedelta(weeks=3)) # 三周后
    print(datetime.datetime.now() + datetime.timedelta(weeks=-3)) # 三周前
    print(datetime.datetime.now() + datetime.timedelta(days=-3)) # 三天前
    print(datetime.datetime.now() + datetime.timedelta(days=3)) # 三天后
    print(datetime.datetime.now() + datetime.timedelta(hours=5)) # 5小时后
    print(datetime.datetime.now() + datetime.timedelta(hours=-5)) # 5小时前
    print(datetime.datetime.now() + datetime.timedelta(minutes=-15)) # 15分钟前
    print(datetime.datetime.now() + datetime.timedelta(minutes=15)) # 15分钟后
    print(datetime.datetime.now() + datetime.timedelta(seconds=-70)) # 70秒前
    print(datetime.datetime.now() + datetime.timedelta(seconds=70)) # 70秒后
    
    current_time = datetime.datetime.now()
    # 可直接调整到指定的 年 月 日 时 分 秒 等
    
    print(current_time.replace(year=1977))  # 直接调整到1977年
    print(current_time.replace(month=1))  # 直接调整到1月份
    print(current_time.replace(year=1989,month=4,day=25))  # 1989-04-25 18:49:05.898601
    
    # 将时间戳转化成时间
    print(datetime.fromtimestamp(1232132131))  # 2009-01-17
    

    random模块

    print(random.random())#在0~1之间随机生成一个浮点数
    print(random.uniform(0,10))#在0~10时间随机生成一个浮点数,可以指定范围
    print(random.randint(1,10))#随机生成一个整数,可以指定范围
    print(random.randrange(1,5,2))#起始终止步长,生成一个数字
    print(random.chioce([1,2,3,4,5,6]))#随机选择一个元素
    print(random.chioces([1,2,3,4,5,6,7]),k=2)#随机选择两个元素,会有重复的
    print(random.sample((1,2,3,4,5,6,7,8)),k=2)#随机选择两个元素,不会有重复的,除非只有两个
    print(random.shuffle(lst))#打乱顺序
    *************************************************
    >>> import random
    #随机小数
    >>> random.random()     # 大于0且小于1之间的小数
    0.7664338663654585
    >>> random.uniform(1,3) #大于1小于3的小数
    1.6270147180533838
    
    #随机整数
    >>> random.randint(1,5)  # 大于等于1且小于等于5之间的整数***
    >>> random.randrange(1,10,2) # 大于等于1且小于10之间的奇数***
    
    #随机选择一个返回
    >>> random.choice([1,'23',[4,5]])  # #1或者23或者[4,5]
    #随机选择多个返回,返回的个数为函数的第二个参数***
    >>> random.choices([1,2,3,4],k=2) # 选择两个元素,会有重复,可控制元素个数***
    >>> random.sample([1,'23',[4,5]],k=2) # #列表元素任意2个组合,不会重复(原列表有重复就会出现重复),可控制元素个数***
    [[4, 5], '23']
    
    #打乱列表顺序
    >>> item=[1,3,5,7,9]
    >>> random.shuffle(item) # 对原列表打乱次序
    >>> item
    [5, 1, 3, 7, 9]
    >>> random.shuffle(item)
    >>> item
    [5, 9, 7, 1, 3]
    

    序列化模块

    • json

      1.dumps loads
              lit = [1,22,3,3,45]
              print(json.dumps(lit),type(json.dumps(lit)))
              str_lst = json.dumps(lit)
              lst = json.loads(str_lst)
              print(lst,type(lst))
      
              dumps 将对象转换(序列化)成字符串
              loads 将字符串转换(反序列化)成对象
      
              dic = {'username':'宝元'}
              str_dic = json.dumps(dic)  # 序列化
              str_dic = json.dumps(dic,ensure_ascii=False)  # ensure_ascii=False 关闭ascii码
              print(str_dic,type(str_dic))
              dic1 = json.loads(str_dic)  # 反序列化
              print(dic1,dic1["username"])
      
      2.dump load
              import json
              lit = [1,22,3,3,45]
              同时写多个内容 进行序列化
              lst = [1,2,3,4,56,]
              f = open("info","w",encoding="utf-8")
              f.write(json.dumps(lst) + "
      ")
              f.write(json.dumps(lst) + "
      ")
              f.write(json.dumps(lst) + "
      ")
              f.write(json.dumps(lst) + "
      ")
              f.write(json.dumps(lst) + "
      ")
              f.close()
      
              dump: 将对象转换(序列化)成字符串,写入文件
              load: 将文件中字符串转换(反序列)成对象
      
              同时读多个内容进行反序列
              f1 = open("info","r",encoding="utf-8")
              for i in f1:
                  l = json.loads(i)
                  print(l)
              f1.close()
      
      
    • pickle模块

      pickle 序列化 - nb(python所有对象进行转换)
      python自带的(只有python可以用)
      两组4个方法:
      1. dumps loads
              import pickle
      
              lst = [12,3,4,5,768]
              t_list = pickle.dumps(lst) # 转换成类似字节
              print(t_list)
              print(pickle.loads(t_list)[-1])
      
              dic = {"user":"郭宝元"}
              t_list = pickle.dumps(dic) # 转换成类似字节
              print(t_list)
              print(pickle.loads(t_list))
      
              def func():
                  print(111)
      
              import json
              fun = json.dumps(func)
              print(fun)
      
              fun = pickle.dumps(func)
              print(fun)
              pickle.loads(fun)()
      
      2. dump  load
      import pickle
      dic = {"usern":"baoyuian"}
      dic = {"usern":"宝元"}
      pickle.dump(dic,open("info","wb"))
      print(pickle.load(open("info","rb")))
      
      import pickle
      dic = {"user":"123"}
      pickle.dump(dic,open("info","ab"))
      
      import pickle
      dic = {"1":2}
      f = open("info","wb")
      s = "
      ".encode("utf-8")
      f.write(pickle.dumps(dic)+ s)
      f.write(pickle.dumps(dic)+ s)
      f.write(pickle.dumps(dic)+ s)
      f.close()
      
      f1 = open("info","rb")
      for i in f1:
          print(pickle.loads(i))
      
      推荐使用json
        json是各种语言通用的
      
      

    os模块

    • os模块是程序员通过python向操作系统发送指令的交互接口

      import os
      #工作目录
      print(os.getcwd())#获取当前的工作路径
      print(os.chdir())#修改工作路径
      print(os.curdir)
      print(os.pardir)
      #文件夹
      print(os.mkdir('aaa'))
      print(os.rmdir('aaa'))
      print(os.makedirs('aaa/bbb/ccc'))
      print(os.removedirs('aaa/bbb/ccc'))
      print(os.listdir('E:python24期笔记day17'))
      #文件相关
      print(os.rename('aa.txt','bb.txt'))#修改文件名
      print(os.remove('sss'))#删除文件
      #路径相关
      print(os.path.abspath('F:oldboyday17os模块.py'))#获取绝对路径
      print(os.path.dirname('F:oldboyday17os模块.py'))#获取文件夹路径
      print(os.path.basename('F:oldboyday17os模块.py'))#获取文件目录
      print(os.path.split('F:oldboyday17os模块.py'))#对文件夹和文件分割
      print(os.path.isabs('F:oldboyday17os模块.py'))#判断是不是绝对路径
      print(os.path.isdir('F:oldboyday17'))#判断是不是一个目录
      print(os.path.isfile('F:oldboyday17os模块.py'))#判断是不是一个文件名
      print(os.path.exists('F:oldboyday17os模块.py'))#判断路径存不存在
      print(os.path.join())#拼接路径
      os.path.getatime()#查看文件的最后访问时间
      os.path.getmtime()#查看文件的最后修改时间
      os.path.getctime()#文件的创建时间
      os.path.getsize()#路径的字节大小,按照kb返回
      

    hashlib模块

    md5,sha1,sha256,sha512
    1.只要明文相同密文就是相同的
    2.只要明文不相同密文就是不相同的
    3.不能反逆(不能解密) -- md5中国人破解了
    加密:
        1.加密的内容
        2.将要加密的内容转成字节
    
    #最常用是的md5,平时加密的时候使用sha1
    #加固定盐
    import hashlib
    md5 = hashlib.md5("常鑫".encode("utf-8"))
    md5.update("alex123".encode("utf-8"))
    print(md5.hexdigest())
    
    md5 = hashlib.md5()
    md5.update("alex123".encode("utf-8"))
    print(md5.hexdigest())
    
    #动态加盐
    user = input("username:")
    pwd = input("password")
    
    import hashlib
    md5 = hashlib.md5(user.encode("utf-8"))
    md5.update(pwd.encode("utf-8"))
    print(md5.hexdigest())
    
    md5 = hashlib.md5()
    md5.update(pwd.encode("utf-8"))
    print(md5.hexdigest())
    
    #767db14ed07b245e24e10785f9d28e29
    
    f = open(r"F:s24day17python-3.6.6-amd64.exe","rb")
    import hashlib
    md5 = hashlib.md5()
    md5.update(f.read())
    print(md5.hexdigest())
    
    ss = "baoyuanalextaibai"
    s = "baoyuan"
    s1 = "alex"
    s2 = "taibai"
    import hashlib
    md5 = hashlib.md5()
    md5.update(ss.encode("utf-8"))
    print(md5.hexdigest())
    
    
    md5 = hashlib.md5()
    md5.update(s.encode("utf-8"))
    md5.update(s1.encode("utf-8"))
    md5.update(s2.encode("utf-8"))
    print(md5.hexdigest())
    
    #节省内存
    
    f = open(r"F:s24day17python-3.6.6-amd64.exe","rb")
    import hashlib
    md5 = hashlib.md5()
    while True:
        msg = f.read(1024)
        if msg:
            md5.update(msg)
        else:
            print(md5.hexdigest())
            break
    

    collections模块

    collections模块
    在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。
    
    1.namedtuple: 生成可以使用名字来访问元素内容的tuple
    
    2.deque: 双端队列,可以快速的从另外一侧追加和推出对象
    
    3.Counter: 计数器,主要用来计数
    
    4.OrderedDict: 有序字典
    
    5.defaultdict: 带有默认值的字典
    ====================================================================================
    #namedtuple
    我们知道tuple可以表示不变数据,例如,一个点的二维坐标就可以表示成:
    
    p = (1, 2)
    但是,看到(1, 2),很难看出这个tuple是用来表示一个坐标的。
    
    这时,namedtuple就派上了用场:
    
    from collections import namedtuple
    Point = namedtuple('Point', ['x', 'y'])
    p = Point(1, 2)
    print(p)
    结果:Point(x=1, y=2)
    
    类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple定义:
    
    namedtuple('名称', [属性list]):
    Circle = namedtuple('Circle', ['x', 'y', 'r'])
    deque
    使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。
    ----------------------------------------------------------------------------------
    #deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:
    
    from collections import deque
    q = deque(['a', 'b', 'c'])
    q.append('x')
    q.appendleft('y')
    q
    deque(['y', 'a', 'b', 'c', 'x'])
    deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。
    ------------------------------------------------------------------------
    #OrderedDict
    使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。
    
    如果要保持Key的顺序,可以用OrderedDict:
    
    from collections import OrderedDict
    d = dict([('a', 1), ('b', 2), ('c', 3)]) # 另一种定义字典的方式
    print(d)
    # 结果:
    {'a': 1, 'c': 3, 'b': 2}
    
    od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
    print(od)
    # 结果:
    OrderedDict([('a', 1), ('b', 2), ('c', 3)])
    注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:
    
    >>> od = OrderedDict()
    >>> od['z'] = 1
    >>> od['y'] = 2
    >>> od['x'] = 3
    >>> od.keys() # 按照插入的Key的顺序返回
    ['z', 'y', 'x']
    --------------------------------------------------------------------------
    #defaultdict
    有如下值集合 [11,22,33,44,55,66,77,88,99,90...],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中。
    
    即: {'k1': 大于66 , 'k2': 小于66}
    
    li = [11,22,33,44,55,77,88,99,90]
    result = {}
    for row in li:
        if row > 66:
            if 'key1' not in result:
                result['key1'] = []
            result['key1'].append(row)
        else:
            if 'key2' not in result:
                result['key2'] = []
            result['key2'].append(row)
    print(result)
    
    from collections import defaultdict
    values = [11, 22, 33,44,55,66,77,88,99,90]
    my_dict = defaultdict(list)
    
    for value in  values:
        if value>66:
            my_dict['k1'].append(value)
        else:
            my_dict['k2'].append(value)
    使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict:
    
    from collections import defaultdict
    dd = defaultdict(lambda: 'N/A')
    dd['key1'] = 'abc'
     # key1存在
    print(dd['key1'])
    dd['key2'] # key2不存在,返回默认值
    print(dd['key2'])
    -------------------------------------------------
    #Counter
    Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似。
    
    c = Counter('abcdeabcdabcaba')
    print c
    输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})
    
    

    re模块

    s='lijie_李杰_l	lilililijiee123@'
    #w匹配字母数字,下划线包括中文
    print(re.findall('w',s))
    #W匹配非字母数字,下划线包括中文
    print(re.findall('W',s))
    #s匹配任意空格,换行符,制表符
    print(re.findall('s',s))
    #S匹配非任意空格,换行符,制表符
    print(re.findall('S',s))
    #d匹配数字
    print(re.findall('d',s))
    #D匹配非数字
    print(re.findall('D',s))
    #A或^匹配开头的内容
    print(re.findall('Alijie',s))
    print(re.findall('^lijie',s))
    #或$匹配结尾的内容
    print(re.findall('123@',s))
    print(re.findall('123@$',s))
    #
     	 匹配换行符和制表符
    print(re.findall('
    ',s))
    print(re.findall('	',s))
    #.匹配任意一个内容(换行符除外)
    print(re.findall('l.j',s))
    print(re.findall('l.j',s,re.DOTALL))#.匹配任意时,可以匹配所有
    #[]指定匹配的范围
    print(re.findall('[A-Za-z0-9]',s))
    #[^]匹配指定范围之外的
    print(re.findall('[^a-z]',s))
    #*匹配0个或多个内容
    print(re.findall('li*',s))#贪婪匹配
    #+匹配1个或多个内容
    print(re.findall('li',s))#贪婪匹配
    #?匹配0个或一个内容
    print(re.findall('li?',s))
    #{}重复匹配指定字符几次
    print(re.findall('l{1}',s))
    #{1,6}指定重复匹配指定字符的次数范围
    print(re.findall('l{1,6}',s))
    #|或者
    print(re.findall('li|jie',s))
    #()匹配括号里的内容
    print(re.findall('l(.+?)j',s))
    print(re.findall('l(?:.+?)l',s))#()匹配时?:可以将括号外面的一起返回
    #search匹配一个,匹配到返回的是一个对象,查看元素用group()方法
    print(re.search('li',s))
    #match从字符串的开头查找,返回一个对象,查看元素用group()方法
    print(re.match('li',s))
    #finditer返回一个迭代器
    a=re.finditer('w','你好世界')
    print(next(a).group())#用group查看值
    #split分割
    print(re.split('l',s))
    #sub替换
    print(re.sub('li','哈哈','lijieljie'))
    #?P分组起名
    print(re.findall('(?P<aaa>w)jie',s).group('aaa'))
    #.转义
    # 匹配所有的数字(包含小数包含负号)
    # print(re.findall("-?d+.d+|-?d+",s))
    
    
    元字符 匹配内容
    w 匹配字母(包含中文)或数字或下划线
    W 匹配非字母(包含中文)或数字或下划线
    s 匹配任意的空白符
    S 匹配任意非空白符
    d 匹配数字
    D p匹配非数字
    A 从字符串开头匹配
    z 匹配字符串的结束,如果是换行,只匹配到换行前的结果
    匹配一个换行符
    匹配一个制表符
    ^ 匹配字符串的开始
    $ 匹配字符串的结尾
    . 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
    [...] 匹配字符组中的字符
    [^...] 匹配除了字符组中的字符的所有字符
    * 匹配0个或者多个左边的字符。
    + 匹配一个或者多个左边的字符。
    匹配0个或者1个左边的字符,非贪婪方式。
    {n} 精准匹配n个前面的表达式。
    {n,m} 匹配n到m次由前面的正则表达式定义的片段,贪婪方式
    a|b 匹配a或者b。
    () 匹配括号内的表达式,也表示一个组

    模块和包

    只要文件夹下含有__init__.py文件就是一个包,包是干什么的呢?
    
    回想一下,之前我们没有学习模块的时候将一个整体的功能写入到文件中,为了能够充分的将某个功能进行重用 我们使用了模块,但是慢慢的模块就会越来越多.我们想提高程序的结构性可维护性,就使用包将模块进行统一管理
    
    包能够管理多个模块,我们想要使用包里的模块怎么办呢?
    
    使用import 和from xx import xx 现有如下结构
    
    bake            
    
        ├── __init__.py       
    
        ├── api               
    
            ├── __init__.py
    
            ├── policy.py
    
            └── versions.py
    
      ├── cmd             
    
        ├── __init__.py
    
        └── manage.py
    
      └── db                
    
          ├── __init__.py
    
          └── models.py
    我们在bake同级创建一个test.py进行导入policy.py 我们使用模块的import的时候只能将api添加到sys.path的路劲中,我们来看看包使用import导入
    
    import bake.api.policy
    bake.api.policy.get()
    导入的太长了下边使用的时候还需要在重复写一遍,我们可以使用as起别名
    
    import bake.api.policy as p
    p.get()
    这样的操作只支持包,普通的文件夹无效,有人一定在想我把bake拿过来然后一层一层的打开那拿工具就可以了
    
    import bake
    bake.api.policy.get()
    不好使,这样导入是只将policy导入了,有人想怎么将api包下的模块全部导入不要急,先说单独导入的方式
    
    咱们能够使用import进行导入,在来看看from的导入方式
    
    from bake.api import policy
    policy.get()
    from bake import api
    print(api.versions.name)
    还是不好使,通过这两个我们能够感觉都导入的时候指定要导入的内容,不能再导入后在进行开箱子
    
    我们现在说了单独导入一个模块,现在来说道说道怎么导入某个包下的所有模块,想要导入某个包下的所有的模块 我们就需要在包中的__init__.py做点手脚
    
    bake包下的__init__.py
    from . import api
    .是当前路径,因为from的时候不能空着
    
    api包下的__init__.py
    from . import policy
    我们将包下的__init__配置好,然后在test.py进行导入
    
    import bake
    bake.api.policy.get()
    又好使了,这是为什么呢?我们import导入bake这个包,因为bake是一个文件夹不能进行任何操作,就让__init__.py代替它 去将api这包中的模块导入,api也是一个文件夹不能操作就需要让api下边的__init__.py去找api下边的两个模块
    
    这个和公司的上下级关系一样,打比方现在test.py就是一个ceo要和policy这个小员工谈话,ceo先把这个想法人事经理,人事经理就是 bake这个包,人事经理通知人事让人事查找一下policy在那个部门,人事查到后通知部门的负责人,部门的负责人在通知部门的主管,主管告诉policy这个员工, 说ceo要找你,部门的主管带着policy去找人事,人事带着policy,人事然后在带着policy去找ceo.最后成功的和ceo进行了一番交流
    
    如果在传达的时候中间一个环节忘记传递了,policy就不知道ceo在找他,ceo等了好久不来ceo就生气报错了
    
    使用的时候需要注意: 有的同学,想在policy文件中导入versions就是直接使用import,在policy文件使用没有问题,很美,很高兴.但是在test.py执行的时候就会报错 因为我们在test.py中执行的import versions 相当于在test.py文件进行查找,肯定不会找到,我们需要在policy文件中向sys.path添加了当前的路劲就可以了 具体操作如下:
    
    import os
    import sys
    sys.path.insert(os.path.dirname(__file__)
    __file__获取的是当前文件的路径,这样我们就能在test中正常使用了,我们使用from也能够将某个包下所有的模块全都导入 比如我们现在想将cmd包下的所有的模块导入需要在bake包下的__init__.py进行设置
    
    from . import *
    我们需要在api包下设置__init__.py
    
    __all__ = ["policy","versions"]
    或
    from . import policy
    from . import versions
    我们需要在db包下设置__init__.py
    
    __all__ = ["models"]
    或
    from . import models
    我们需要在cmd包下设置__init__.py
    
    __all__ = ["manage"]
    或
    from . import manage
    以上两种推荐使用下from . import manage 灵活,可读性高
    
    test.py调用如下:
    
    from bake.api import *
    print(versions.name)
    policy.get()
    
    from bake.db import *
    models.register_models(123)
    
    from bake.cmd import *
    print(manage.name)
    在使用import有个注意点,python2中如果import包,没有__init__.py文件就会报错 python3 import没有__init__.py文件的包不会报错 from 包 import 包或者模块(在import后边不能在进行.操作)
    
    路径: 绝对路径:从最外层(bake)包.查找的就是绝对路径 相对路径:.就是相对路径, ..是上一级目录 例如:我们在bake/api/version.py中想要导入bake/cmd/manage.py
    
    # 绝对路径:
    from bake.cmd import manage
    manage.main()
    
    #相对路径:
    from ..cmd import manage
    manage.main()
    注意在使用相对路径的时候一定要在于bake同级的文件中测试 我们需要在和bake同级的test.py中测试
    
    from bake.cmd import manage
    

    logging日志模块

    其实每个软件都是有错误日志的,开发人员可以通过错误日志中的内容对他的程序进行修改
    
    这只是一种应用场景,有的还会将日志用于交易记录.比如你给我转账应该做记录吧,
    
    我们使用的信用卡,每消费的一笔都会记录,我们来看看这个日志怎么用?
    
    我们先来看一下函数式简单配置
    
    import logging  
    logging.debug('debug message')  
    logging.info('info message')  
    logging.warning('warning message')  
    logging.error('error message')  
    logging.critical('critical message')
    默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING
    
    (日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG),
    
    默认的日志格式为日志级别:Logger名称:用户输出消息。
    
    我们自己用函数写的这个可以正常使用但是不够灵活,我们看看这个灵活的
    
    灵活配置日志级别,日志格式,输出位置:
    
    import logging  
    logging.basicConfig(level=logging.DEBUG,  
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
                        datefmt='%a, %d %b %Y %H:%M:%S',  
                        filename='/tmp/test.log',  
                        filemode='w')  
    
    logging.debug('debug message')  
    logging.info('info message')  
    logging.warning('warning message')  
    logging.error('error message')  
    logging.critical('critical message')
    basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
    
    filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
    filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
    format:指定handler使用的日志显示格式。
    datefmt:指定日期时间格式。
    level:设置记录日志的级别
    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')
    logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。另外,可以通过:logger.setLevel(logging.Debug)设置级别,当然,也可以通过
    
    fh.setLevel(logging.Debug)单对文件流设置某个级别。
    ================================================================
    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')
    

    logging日志旗舰版

    """
    logging配置
    """
    
    import os
    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'
    
    id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
    
    # 定义日志输出格式 结束
    
    logfile_dir = os.path.dirname(os.path.abspath(__file__))  # log文件的目录
    
    logfile_name = 'all2.log'  # log文件名
    
    # 如果不存在定义的日志目录就创建一个
    if not os.path.isdir(logfile_dir):
        os.mkdir(logfile_dir)
    
    # log文件的全路径
    logfile_path = os.path.join(logfile_dir, logfile_name)
    
    # 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)传递
            },
        },
    }
    
    
    def load_my_logging_cfg():
        logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
        logger = logging.getLogger(__name__)  # 生成一个log实例
        logger.info('It works!')  # 记录该文件的运行状态
    
    if __name__ == '__main__':
        load_my_logging_cfg()
    

  • 相关阅读:
    设计模式总结
    JWT、OAUTH2与SSO资料补充
    dajie项目的坑
    fw-cloud-framework项目配置、启动问题
    Shiro源码分析
    (转)JPA & Restful
    Spring Boot以War包启动
    (转)Spring & SpringMVC学习
    MySQL的数据类型(二)
    MySQL的数据类型(一)
  • 原文地址:https://www.cnblogs.com/luckinlee/p/11620324.html
Copyright © 2020-2023  润新知