面向对象学习笔记(5)

part5

1.单例模式

无论实例化多少次,永远用的都是第一次实例化出的对象。

class Foo:
    pass

# 多例,每实例化一次就创建一个新的对象(即多开一块空间)
obj1 = Foo()
obj2 = Foo()
# 单例,无论实例化多少次都用第一次创建的那个对象。
# ##########多例模式#########
# class Singleton(Object):
#     pass
#
# obj1 = Singleton()
# obj2 = Singleton()
# print(obj1,obj2)
# # <__main__.Foo object at 0x000002E725678400> <__main__.Foo object at 0x000002E725656640>

############单例模式###########
class Singleton(object):
    instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.instance:
            cls.instance = object.__new__(cls)
        return cls.instance
obj1 = Singleton()
obj2 = Singleton()
print(obj1,obj2)
# <__main__.Foo object at 0x0000018774120340> <__main__.Foo object at 0x0000018774120340>

不是最终的形式,以上只是帮助了解。(最终需要加锁)

应用场景:数据库连接和连接池

# 文件连接池
class FileHelper:
    instance = None
    def __init__(self,path):
        self.file_object = open(path,mode="r",encoding="utf-8")
    def __new__(cls, *args, **kwargs):
        if not cls.instance:
            cls.instance = object.__new__(cls)
        return cls.instance

obj1 = FileHelper('text5_1.txt')
obj2 = FileHelper('text5_1.txt')
print(obj1.file_object.read(1))
print(obj2.file_object.read(10))

通过模块导入的特性也可以实现单例模式:

# child.py
class Foo:
    pass

obj = Foo()
# main.py
import child # 加载child.py后会实例化一个Foo对象并赋值给obj
print(child.obj)
print(child.obj)
# 以上两个对象是公用一块内存的

2.日志(logging模块)

import logging
logging.basicConfig(filename='daylog1.log',level=20)
logging.log(10,'10') # <20不会执行
logging.log(30,'30') # >20会执行

# level一般不会自己去写
# 在logging.ERROR里可以查看到以下信息
# CRITICAL = 50 => 崩溃严重错误
# FATAL = CRITICAL
# ERROR = 40 => 错误
# WARNING = 30 => 警告
# WARN = WARNING
# INFO = 20 => 正常信息
# DEBUG = 10 => 调试
# NOTSET = 0 => 不设置

logging.basicConfig(filename='daylog2.log',level=logging.INFO)
logging.log(10,'10')
logging.debug('10') # 效果同上
logging.log(30,'30') # >20会执行
logging.warn('30') # 效果同上(横线代表将会被移除),所以使用以下的格式
logging.warning('30') # 效果一样
1.快速使用
import logging
# 配置信息(多次配置是无效的,只会执行第一次)
logging.basicConfig(
    filename='daylog.log',
    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S %p',
    level=logging.ERROR
)
logging.error('a1')
# 相关信息参考:https://www.cnblogs.com/wupeiqi/articles/5501365.html

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

import logging
import requests

logging.basicConfig(
    filename='daylog.log',
    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S %p',
    level=logging.ERROR
)
try:
    requests.get('http://www.xxx.com')
except Exception as e:
    msg = str(e) # 调用e.__str__方法
    logging.error(msg,exc_info=True) # exc_info=True => 会将堆栈信息一起返回

basicConfig的底层(本质):

import logging
# 指定日志文件
file_handler = logging.FileHandler('x1.log', 'a', encoding='utf-8')
# 规定格式要求
fmt = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s")
# 将要求赋给指定的日志文件
file_handler.setFormatter(fmt)
# 创建一个写日志的对象
logger = logging.Logger('s1', level=logging.ERROR)
# 告诉该对象上述指定的日志文件规则
logger.addHandler(file_handler)
# 进行日志书写
logger.error('hello world!')
logger.error('你好')
2.一次写入多个文件
# 一次写入多个文件
import logging

file_handler1 = logging.FileHandler('x1.log', 'a', encoding='utf-8')
fmt1 = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s")
file_handler1.setFormatter(fmt1)

file_handler2 = logging.FileHandler('x2.log', 'a', encoding='utf-8')
fmt2 = logging.Formatter(fmt="%(asctime)s :  %(message)s")
file_handler1.setFormatter(fmt2)

logger = logging.Logger('s1', level=logging.ERROR)
# 将所有的文件对象都添加给logger对象(这样满足条件的文件可以同时写入)
logger.addHandler(file_handler1)
logger.addHandler(file_handler2)

logger.error('hello world!')
logger.error('你好')
3.推荐日志方式
import logging

file_handler = logging.FileHandler('standard.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('你好')
logging.error('hello world!')
4.日志切割
import logging
import time
from logging import handlers

file_handler = handlers.TimedRotatingFileHandler(filename='log/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,20):
    time.sleep(1)
    logging.error(str(i))

3.项目目录结构

1.脚本

内置模块在第三方模块上方,模块按名字由短至长排列。

在这里插入图片描述

2.单可执行文件

src:业务相关的功能(登陆注册、购买商品等等)

lib:公共的代码、类、库(比如分页代码)

db:存放数据

config:存放配置文件

log:存放日志文件

在这里插入图片描述

3.多可执行文件

在这里插入图片描述

示例

在这里插入图片描述

# student.py
from src.run import start

if __name__ == '__main__':
    start()
# settings.py
import os

# 获取到example这个根文件的路径
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(BASE_DIR)

# 修改日志名字在这里不用去动代码了
LOG_FILE_NAME = "cmdb.log"
LOG_FILENAME = os.path.join(BASE_DIR,'log',LOG_FILE_NAME)
LOG_WHEN = "s"
LOG_INTERVAL = 5
# log.py
# 此处为了方便,一般把日志存放在项目之外(将日志保存路径修改即可)
import os
import logging
from config import settings
from logging import handlers

def get_logger():
    # 如果要切割日志也是在该文件中操作
    # file_handler = handlers.TimedRotatingFileHandler(filename=LOG_FILE_NAME,
    #                                                  when=settings.LOG_WHEN,
    #                                                  interval=settings.LOG_INTERVAL,
    #                                                  encoding='utf-8')
    file_handler = logging.FileHandler(settings.LOG_FILE_NAME, 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
    )
    return logging

logger = get_logger()
# account.py
from lib.log import logger

def login():
    print("登录")
    # 捕获异常
    try:
        int("sad")
    except Exception as e:
        print("出错!请重新输入")
        # import logging
        # logging.error(str(e),exc_info=True)
        logger.error(str(e),exc_info=1) # 效果同上


def register():
    print("注册")
# order.py
def manger():
    print("订单")
# run.py
from src import account
from src import order

def start():
    print("1.登录;2.注册;3.订单管理")
    func_dict = {'1':account.login,'2':account.register,'3':order.manger}
    choice = input("请选择:")
    func = func_dict.get(choice)
    if not func:
        print("输入错误")
    func()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值