包以及日志的初识和使用

包以及log日志

包的使用

官网解释

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. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是一种模块

  3. import

    # 第一类: 执行文件 通过 import 导入包以及包内的功能
    # 创建一个aaa的包,自行创建一个__init__py文件
    # 回忆 :创建一个tbjx模块发生的三件事:
    '''
        1. 将该tbjx文件加载到内存.
        2. 创建一个以tbjx命名的名称空间.
        3. 通过tbjx. 的方式引用tbjx模块的所有的名字.
    '''
    
    # 创建一个包,也会发生三件事:
    '''
        1. 将该aaa包内 __init__py文件加载到内存.
        2. 创建一个以aaa命名的名称空间.
        3. 通过aaa. 的方式引用__init__的所有的名字.
    '''
    import aaa
    # print(aaa.x)
    # aaa.f1()
    
    # print(aaa.m1)
    # print(aaa.m1.a)
    
    # 我想要引用 aaa包的m1文件的a变量
    # 错误示例1:
    import aaa
    # 1. aaa的 __init__ 里面 写import m1
    # 2. print(aaa.m1.a)
    # print(aaa.m1.a)
    
    # 报错原因: No module named 'm1'
    # 分析报错原因: 模块找不到 内存,内置,sys.path三个地方找不到.
    # m1 不在内存,不在内置,sys.path 会主动加载执行文件(包的使用.py)的当前目录.
    
    # 解决方式:
    import aaa
    # 1. 在执行文件写入 import aaa
    # 2. aaa的 __init__ 里面 写 from aaa import m1
    # 3. 然后在执行文件  aaa.m1.a
    # print(aaa.m1.a)
    
    # aaa.m1.func1()
    
    
    import aaa
    # 如何在当前文件中,引用 aaa包的bbb包.
    # 1. 在执行文件写入 import aaa
    # 2. aaa的 __init__ 里面 写 from aaa import bbb
    # 3. 然后在执行文件  aaa.bbb
    # print(aaa.bbb)
    
    
    # 如何在当前文件中,引用 aaa包的bbb包 的 变量 name.
    # 1. 在执行文件写入 import aaa
    # 2. aaa的 __init__ 里面 写 from aaa import bbb
    # 3. 然后在执行文件  aaa.bbb
    # print(aaa.bbb)
    
    
    import aaa
    # print(aaa.bbb.name)
    
    # 如何在当前文件中,引用 aaa包的bbb包 的 mb文件的函数func.
    
    # 1. 在执行文件写入 import aaa
    # 2. 在aaa包的__Init__ 写上 from aaa import bbb  (这样写 bbb包的__init__里面所有的名字都能引用)
    # print(aaa.bbb.name)
    # 3. 在bbb包的__Init__ 写上 from aaa.bbb import mb
    # aaa.bbb.mb.func3()
    
    # 首先 无论从哪里引用模块,import 或者 from  ... import ...
    # 最开始的模块或者包名一定是内存,内置,sys.path中能找到的.(可参考bbb包中的 __init__)
    
    # 直接import 为了让我们会使用 包里面的 __init__
    
    第二类: 执行文件 通过 from ... import... 导入包以及包内的功能
  4. from ... import ...

    # from ... import ...
    # 通过这种方式不用设置__init__文件
    # from aaa import m1
    # m1.func()
    
    # from aaa.bbb.m2 import func1
    # func1()
    # from aaa.bbb import m2
    # m2.func1()
    
    # from a.b.c import d.e.f
    # c的. 的前面一定是包
    # import 的后面一定是名字,并且不能 再有点
    
    # from aaa.bbb.m2.func1 import a  # 错误的
    # from aaa.bbb import m2
    # m2.func1()
    
    import json
  5. 相对导入与绝对导入

    我们的最顶级包glance是写给别人用的,然后在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:

    绝对导入:以glance作为起始

    相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)

    例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py

    在glance/api/version.py
    
    #绝对导入
    from glance.cmd import manage
    manage.main()
    
    #相对导入
    from ..cmd import manage
    manage.main()

    包以及包所包含的模块都是用来被导入的,而不是被直接执行的。而环境变量都是以执行文件为准的

    比如我们想在glance/api/versions.py中导入glance/api/policy.py,有的同学一抽这俩模块是在同一个目录下,十分开心的就去做了,它直接这么做

    #在version.py中
    
    import policy
    policy.get()

    没错,我们单独运行version.py是一点问题没有的,运行version.py的路径搜索就是从当前路径开始的,于是在导入policy时能在当前目录下找到

    但是你想啊,你子包中的模块version.py极有可能是被一个glance包同一级别的其他文件导入,比如我们在于glance同级下的一个test.py文件中导入version.py,如下

    from glance.api import versions
    
    '''
    执行结果:
    ImportError: No module named 'policy'
    '''
    
    '''
    分析:
    此时我们导入versions在versions.py中执行
    import policy需要找从sys.path也就是从当前目录找policy.py,
    这必然是找不到的
    '''

    相对导入和绝对导入的总结

    绝对导入与相对导入
    
    # 绝对导入: 以执行文件的sys.path为起始点开始导入,称之为绝对导入
    #        优点: 执行文件与被导入的模块中都可以使用
    #        缺点: 所有导入都是以sys.path为起始点,导入麻烦
    
    # 相对导入: 参照当前所在文件的文件夹为起始开始查找,称之为相对导入
    #        符号: .代表当前所在文件的文件加,..代表上一级文件夹,...代表上一级的上一级文件夹
    #        优点: 导入更加简单
    #        缺点: 只能在导入包中的模块时才能使用
          #注意:
            1. 相对导入只能用于包内部模块之间的相互导入,导入者与被导入者都必须存在于一个包内
            2. attempted relative import beyond top-level package # 试图在顶级包之外使用相对导入是错误的,言外之意,必须在顶级包内使用相对导入,每增加一个.代表跳到上一级文件夹,而上一级不应该超出顶级包

工作日志分四个大类:

  1. 系统日志:记录服务器的一些重要信息:监控系统,cpu温度,网卡流量,重要的硬件的一些指标,运维人员经常使用的,运维人员,记录操作的一些指令.
  2. 网站日志: 访问异常,卡顿,网站一些板块,受欢迎程度,访问量,点击率.等等,蜘蛛爬取次数等等.
  3. 辅助开发日志: 开发人员在开发项目中,利用日志进行排错,排除一些避免不了的错误(记录),辅助开发.
  4. 记录用户信息日志: 用户的消费习惯,新闻偏好,等等.(数据库解决)

日志模块

旗舰版日志
"""
logging配置
"""


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_name = 'login.log'  # log文件名
logfile_path_staff = r'E:\老男孩学习\JiaoXueJiHua\day19\day19\日志模块\staff.log'
logfile_path_boss = r'E:\老男孩学习\JiaoXueJiHua\day19\day19\日志模块\boss.log'
logfile_path_login = r'E:\老男孩学习\JiaoXueJiHua\day19\day19\日志模块\login.log'

# log配置字典
# LOGGING_DIC第一层的所有的键不能改变

LOGGING_DIC = {
    'version': 1,  # 版本号
    'disable_existing_loggers': False,  # 固定写法
    'formatters': {
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format
        },
        'id_simple':{
            'format': id_simple_format
        }
    },
    'filters': {},#过滤
    'handlers': {
        #打印到终端的日志
        'sh': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'id_simple'
        },
        #打印到文件的日志,收集info及以上的日志
        'fh': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',
            'filename': logfile_path_staff,  # 日志文件
            'maxBytes': 5000,  # 日志大小 5M
            'backupCount': 5,
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
        'boss':
            {
                'level': 'DEBUG',
                'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
                'formatter': 'id_simple',
                'filename': logfile_path_boss,  # 日志文件
                'maxBytes': 5000,  # 日志大小 5M
                'backupCount': 5,
                'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
            },
    },
    'loggers': {
        #logging.getLogger(__name__)拿到的logger配置
        '': {
            'handlers': ['sh', 'fh', 'boss'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': True,  # 向上(更高level的logger)传递
        },
    },
}


def md_logger():
    logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
    logger = logging.getLogger("login.log")  # 生成一个log实例
    return logger
    logger.debug('It works!')  # 记录该文件的运行状态
dic = {
    'username': '小黑'
}
def login():
    # print('登陆成功')
    md_logger().info(f"{dic['username']}登陆成功")
#
# def aricle():
#     print('欢迎访问文章页面')


login()
# aricle()

Low版(文件与屏幕输入只能选择一个)

# import logging
# logging.basicConfig(
#     level=logging.DEBUG,
# )
# # logging.debug('debug message')
# # logging.info('info message')
# # logging.warning('warning message')
# # logging.error('error message')
# # logging.critical('critical message')

# 应用:
# def func():
#     print('in func')
#     logging.debug('正常执行')
# func()

# try:
#     i = input('请输入选项:')
#     int(i)
# except Exception as e:
#     logging.error(e)
# print(11)

# low版的日志:缺点: 文件与屏幕输入只能选择一个.
import logging
logging.basicConfig(
    # level=logging.DEBUG,
    level=30,
    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
    filename=r'test.log',
)
# logging.debug('调试模式')  # 10
# logging.info('正常模式')  # 20
logging.warning('警告信息')  # 30
# logging.error('错误信息')  # 40
# logging.critical('严重错误信息')  # 50

标配版日志(文件和屏幕)

# import logging
#
# # 创建一个logging对象
# logger = logging.getLogger()
#
# # 创建一个文件对象
# fh = logging.FileHandler('标配版.log', encoding='utf-8')
#
# # 创建一个屏幕对象
# sh = logging.StreamHandler()
#
# # 配置显示格式
# formatter1 = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
# formatter2 = logging.Formatter('%(asctime)s %(message)s')
# fh.setFormatter(formatter1)
# sh.setFormatter(formatter2)
#
# logger.addHandler(fh)
# logger.addHandler(sh)
#
# # 总开关
# logger.setLevel(10)
#
# fh.setLevel(10)
# sh.setLevel(40)
#
# logging.debug('调试模式')  # 10
# logging.info('正常模式')  # 20
# logging.warning('警告信息')  # 30
# logging.error('错误信息')  # 40
# logging.critical('严重错误信息')  # 50

猜你喜欢

转载自www.cnblogs.com/-777/p/11116580.html