zoukankan      html  css  js  c++  java
  • 项目开发规范、time模块、日志

    . 昨日内容回顾
    自定义模块
    import tbjx

    1.创建一个以 tbjx 命名的名称空间
    2.执行此模块的代码,并将所有内容加载到内存
    3.调用此模块的代码要通过 tbjx. 的方式

    改名:
    import time as t
    1.使代码更简洁
    2.优化代码

    import a
    import b
    import c

    from tbjx import name,read1
    1.创建一个以 tbjx 命名的名称空间
    2.执行此模块的代码,并将所有内容加载到内存
    3.直接将 name read1 加载到当前文件的全局中
    好处:使用方便
    缺点:容易与本文件同名的变量,函数冲突

    from tbjx import functools as func

    from tbjx import *
    1.创建一个以 tbjx 命名的名称空间
    2.执行此模块的代码,并将所有内容加载到内存
    3.直接将 tbjx 模块中所有的内容全部复制一份到当前文件中

    __all__ = ["name", "read1"]

    文件的使用:
    1.当脚本或者代码块,运行本文件的所有代码
    2.当作一个模块,被其他模块调用
    __name__
    本文件使用,相当于 __main__
    其他文件,__name__ == "被调用的模块名"

    __name__ == "__main__":
    1.可以在本模块下,测试自己的代码
    2.项目的执行文件使用

    解释器是按照一定的顺序和位置去寻找模块
    搜索路径:内存--->内置模块--->sys.path[此列表的第一个元素是当前文件的路径]

    想在不同的文件夹下调用模块?
    将模块的路径添加到sys.path中

    import sys
    print(sys.modules)
    程序一运行,解释器会把所有这些 modules 先加载到内存中



    .项目开发规范
    代码不可能只写在一个文件中,否则调整和修改都很不方便,所以要将代码规范化:
    目录规范化,代码规范化(PEP8)

    目录规范化的好处?
    1.项目结构清晰,便于查找
    2.对项目修改时,易于调试

    # 三.time模块,datetime模块
    
    import time
    print(time.time())
    print(time.sleep(1))
    
    # time模块提供的时间有三种模式
    # 第一种形式
    # time.time() 时间戳——从1970.1.1 0:00距今的时间,供计算机使用
    import time
    print(time.time())
    
    # 第二种形式(格式化时间)
    # 2019/1/8 10:39 strftime()
    import time
    ft = time.strftime("%Y-%m-%d")
    ft = time.strftime("%Y/%m/%d")
    ft = time.strftime("%Y/%m/%d %I%M%S")
    ft = time.strftime("%Y{}%m{}%d %I:%M:%S").format("", "", "")
    print(ft)  # 2019年01月08 10:55:19
    
    # 第三种形式:结构化时间以元组的形式存在
    # 作为格式化时间与时间戳进行转化的中转
    import time
    struct_time = time.localtime()
    print(struct_time)
    # time.struct_time(tm_year=2019, tm_mon=1, tm_mday=8, tm_hour=10,
    # tm_min=56, tm_sec=56, tm_wday=1, tm_yday=8, tm_isdst=0)
    print(struct_time[0])  # 2019
    print(struct_time.tm_year)  # 2019
    
    # 三种格式之间的转化
    # 时间戳 ---> 格式化时间
    import time
    timestamp = time.time()
    # 先将时间戳转化成结构化时间
    st = time.localtime(timestamp)
    ft = time.strftime("%Y{}%m{}%d %I:%M:%S", st).format("", "", "")
    print(ft)  # 2019年01月08 11:00:59
    
    # 格式化时间 ---> 时间戳
    import time
    ft = time.strftime("%Y/%m/%d %I:%M:%S")
    # 先将格式化时间转化成结构化时间
    st = time.strptime(ft, "%Y/%m/%d %I:%M:%S")
    print(st)
    # time.struct_time(tm_year=2019, tm_mon=1, tm_mday=8, tm_hour=11,
    tm_min=3, tm_sec=58, tm_wday=1, tm_yday=8, tm_isdst=-1)
    
    # 另一种转化方式
    # 结构化时间 ---> 格式化时间  格式固定
    import time
    strut_time = time.localtime()
    st = time.asctime(strut_time)
    print(st)  # Tue Jan  8 11:10:57 2019
    
    # 时间戳 ---> 格式化时间  格式固定
    import time
    print(time.ctime(15000000000))  # Mon May  1 10:40:00 2445
    
    
    
    # 时间差的计算
    # 2019 1 8 11
    # 2016 9 16 12
    # 第一步,将这两个格式化时间转化成时间戳
    
    import time
    now_time = time.strftime("%Y/%m/%d %H:%M:%S")
    now_timestamp = time.mktime(time.strptime(now_time, "%Y/%m/%d %H:%M:%S"))
    
    old_time = time.strftime("2016/9/16 12:00:00")
    old_timestamp = time.mktime(time.strptime(old_time, "%Y/%m/%d %H:%M:%S"))
    
    dif_time = now_timestamp - old_timestamp
    # print(time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(dif_time)))
    struct_time = time.gmtime(dif_time)
    
    msg = "过去了%d年%d月%d天%d小时%d分钟%d秒" % (struct_time.tm_year-1970,struct_time.tm_mon-1,
                                              struct_time.tm_mday-1,struct_time.tm_hour,
                                              struct_time.tm_min,struct_time.tm_sec)
    print(msg)  
    # 过去了2年3月22天23小时29分钟55秒
    # datetime
    
    import datetime
    now_time = datetime.datetime.now()
    print(now_time)  # 2019-01-08 11:30:56.074414
    print(now_time + datetime.timedelta(weeks=3))  # 三周前
    print(now_time + datetime.timedelta(weeks=3))  # 三周后
    # print(now_time + datetime.timedelta(years=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秒后
    
    # 可以直接调整
    print(now_time.replace(year=2010))  # 2010-01-08 11:34:20.476402
    print(now_time.replace(month=10))   # 2019-10-08 11:35:10.009449
    print(now_time.replace(year=2010, month=10, day=23))  # 2010-10-23 11:36:25.877321
    
    # 将时间戳转化成时间
    print(datetime.date.fromtimestamp(1232132131))  # 2009-01-17
    .日志
    个性化推荐 —— 淘宝,京东,知乎,网易云音乐
    只要做了记录,就可以当作广义的日志

    开发中的日志
    1.帮助调试代码 一个py文件中,使用print()太多,耗费性能大
    2.代码警告,危险提示作用
    3.对服务器的操作命令
    4.重要的节点,需要日志提示,比如转账
    # 日志分三种配置:
    
    # 低配——不能同时显示和写入
    import logging
    logging.debug('debug message')          # 调试模式
    logging.info('info message')            # 正常运转模式
    logging.warning('warning message')      # 警告模式
    logging.error('error message')          # 错误模式
    logging.critical('critical message')    # 致命模式
    # WARNING:root:warning message
    # ERROR:root:error message
    # CRITICAL:root:critical message
    
    
    import logging
    while 1:
        try:
            num = input(">>>")
            int(num)
        except ValueError:
            logging.warning("输入了非数字元素,警告!")
    
    # 指定显示信息格式
    import logging
    logging.basicConfig(
        level=logging.DEBUG,
        # 可以设置级别 把上面的注释掉,然后写下面的
        # level=20,
        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')
    # Tue, 08 Jan 2019 12:14:58 abc.py[line:214]                     DEBUG debug message
    # Tue, 08 Jan 2019 12:14:58 abc.py[line:215]                     INFO info message
    # Tue, 08 Jan 2019 12:14:58 abc.py[line:216]                     WARNING warning message
    # Tue, 08 Jan 2019 12:14:58 abc.py[line:217]                     ERROR error message
    # Tue, 08 Jan 2019 12:14:58 abc.py[line:218]                     CRITICAL critical message

    默认情况下Pythonlogging模块将日志打印到了标准输出中
    且只显示了大于等于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="test.log",
                        filemode="w")
    
    logging.debug("debug message")
    logging.info("info message")
    logging.warning("warning message")
    logging.error("error message")
    logging.critical("critical message")
    灵活配置日志级别,日志格式,输出位置

    这个日志是对本文件的记录



    以下所谓加上,是指在logging.basicConfig()中,显示是在Logger所属 filename 中

    logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为

    1. level: 设置rootlogger的日志级别

    2. format: 指定handler使用的日志显示格式
    format参数中可能用到的格式化信息有以下内容:
    %(name)s——Logger的名字
    这里如果加上的话,显示是root
    %(levelno)s——数字形式的日志级别
    这里加上的话逐行显示10,20,30,40,50
    %(levelname)s——文本形式的日志级别
    %(pathname)s——调用日志输出函数的模块的完整路径名,可能没有
    显示本文件的绝对路径
    这里加上的话,会有乱码,因为路径中有中文字符
    %(filename)s——调用日志输出函数的模块的文件名
    这里是本文件名,123asda.py
    %(module)s——调用日志输出函数的模块名
    这里加上的话,是 123asda
    %(funcName)s——调用日志输出函数的函数名
    这里加上的话,因为从上面到这里都还没函数
    所以显示是 <module>
    %(lineno)d——调用日志输出函数的语句所在的代码行
    即比如下面的 logging.debug("debug message")
    显示是在本文件的第几行,这五个都会显示
    %(created)f——当前时间,用Unix标准的表示时间的浮点数表示
    这里加上的话,显示 1547727721.904610
    %(relativeCreated)d——输出日志信息时间,自Logger创建以来的毫秒数
    %(asctime)s——字符串形式的当前时间
    比如这里加上显示:Thu, 17, Jan 2019 20:27:49
    %(thread)d——线程ID,可能没有
    这里加上显示:7536
    %(threadName)s——线程名,可能没有
    这里加上显示:MainThread
    %(process)d——进程ID,可能没有
    这里加上显示:7692
    %(messages)s——用户输出的消息

    3. datefmt: 指定 format 中 asctime 的显示格式

    4. filename: 用指定的文件名创建FileHandler,这样日志会被存储在指定的文件中

    5. filemode: 文件打开方式,在指定了 filename 时使用这个参数,默认为"a"

    6. stream: 用指定的stream创建StreamHandler, 可以指定输出到sys.stderr,
    sys.stdout或者文件(f=open("test.log","w")), 默认为sys.stderr.
    如果同时列出了filename和stream两个参数,stream会被忽略
    import logging
    
    # 创建一个logger对象
    logger = logging.getLogger()
    
    # 创建一个handler,用于写入日志文件
    fh = logging.FileHandler("test.log", encoding="utf-8")
    # 设置级别
    fh.setLevel(logging.DEBUG)
    # 这里 DEBUG 改为 INFO 在 test.log中也只显示 WARNING 以上级别的信息
    
    # 再创建一个handler, 用于输出到控制台
    ch = logging.StreamHandler()
    
    # 设置显示格式,并将此格式传到两个handler中
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)
    
    # 给logger对象添加两个handler
    logger.addHandler(fh)
    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")
    
    # 与本文件同一个目录下,还会创建一个 test.log文件,输出信息和下面的一样
    # 2019-01-17 21:01:52,674 - root - WARNING - logger warning message
    # 2019-01-17 21:01:52,674 - root - ERROR - logger error message
    # 2019-01-17 21:01:52,674 - root - CRITICAL - logger critical message
    # 标配
    
    import logging
    
    # 1.产生 logger 对象
    logger = logging.getLogger()
    
    # 2.产生其他对象(屏幕对象,文件对象)
    sh = logging.StreamHandler()
    fh1 = logging.FileHandler("staff.log", encoding="utf-8")
    fh2 = logging.FileHandler("boss.log", encoding="utf-8")
    
    # 3.设置显示格式
    formater = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
    formater1 = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
    formater2 = logging.Formatter('%(asctime)s-%(message)s')
    
    # 4.给对象绑定格式
    sh.setFormatter(formater)
    fh1.setFormatter(formater1)
    fh2.setFormatter(formater2)
    
    # 5.给 logger 对象绑定其他对象
    logger.addHandler(sh)
    logger.addHandler(fh1)
    logger.addHandler(fh2)
    
    # 6.设置显示级别
    # 其他对象的级别要高于 logger 的级别
    logger.setLevel(40)
    sh.setLevel(20)
    fh1.setLevel(30)
    fh2.setLevel(50)
    
    logging.debug('debug message')
    logging.info('info message')
    logging.warning('warning message')
    logging.error('error message')
    logging.critical('critical message')
    
    # 2019-01-08 12:40:42,240-root-ERROR-error message
    # 2019-01-08 12:40:42,240-root-CRITICAL-critical message
    logging库提供了多个组件:Logger, Handler, Filter, Formatter
    Logger对象提供应用程序可直接使用的接口
    Handler发送日志到适当的目的地
    Filter提供了过滤日志信息的方法


    logger的配置文件
    上面方式是通过logger对象配置完成日志功能,需要创建各种对象
    下面是以字典方式创建logger配置文件,也是实际工作中的做法,相当于一个模板
    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]"
    
    simple_format = "[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d][%(message)s]"
    
    id_simple_format = "[%(levelname)s][%(asctime)s][%(message)s]"
    
    # 设置 log 文件路径
    logfile_dir = os.path.dirname(os.path.abspath(__file__))
    
    # 设置 log 文件名
    logfile_name = "test.log"
    
    # 如果不存在定义的日志目录就创建一个
    if not os.path.isdir(logfile_dir):
        os.mkdir(logfile_dir)
    
    # log配置字典
    LOGGING_DIC = {
        "version": 1,
        "disable_existing_loggers": False,
        "formatters": {
            "standard": {
                "format": standard_format
            },
            "simple": {
                "format": simple_format
            }
        },
        "filters": {},
        # 打印到屏幕的日志
        "screen": {
            "level": "DEBUG",
            "class": "logging.StreamHandler",
            "formatter": "simple"
        },
        # 打印到文件的日志,收集 INFO 及以上的日志
        "file":{
            "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配置
            "": {
                # 把上面定义的两个handler都加上,即log数据即写入文件又打印到屏幕
                "handlers": ["screen", "file"],
                # 总级别,一定要设置最低的,即 DEBUG
                "level": "DEBUG",
                # 向上(更高level的logger)传递
                "propagate": True,
            },
        },
    }
    
    def load_my_logging_cfg():
        # 导入上面定义的logging配置
        logging.config.dictConfig(LOGGING_DIC)
        logger = logging.getLogger("转账业务")
        logger.info("It works!")  # 记录该文件的运行状态
    
    if __name__ == "__main__":
        load_my_logging_cfg()
  • 相关阅读:
    reduce端的连接实现
    Failed to stop mariadb.service: Interactive authentication required.
    Underlying cause: java.sql.SQLException : Access denied for user 'root'@'s150' (using password: YES)
    java.net.ConnectException: Call From s150/192.168.109.150 to s150:8020 failed on connection excepti
    启动hive出现 org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.ipc.StandbyExceptio
    hive learing_1
    在hive中执行sql语句:SemanticException org.apache.hadoop.hive.ql.metadata.HiveException:
    MariaDB [(none)]> drop user cr; ERROR 1396 (HY000): Operation DROP USER failed for 'cr'@'%'
    ThreadGroupAPI
    使用setUncaughtExceptionHandler在线程外面捕获异常
  • 原文地址:https://www.cnblogs.com/shawnhuang/p/10238950.html
Copyright © 2011-2022 走看看