• python闯关_Day012


    day012 用python实现信息卡管理及购物商城的项目

    需求

    #需求:
    1 这是一个信用卡管理程序
    2 用户手持信用卡购物,使用函数,按照软件开发规范
    3 用户名密码存放于文件中,支持多用户登陆,使用json
    4 程序启动,先登录或者注册,保存信息到文件中,记录日志
    5 用户的登陆,密码输错三次,锁定,不能再登录
    6 用户可以取现,消费,还款,提额
    7 允许用户根据商品编号购买商品,用户选择商品,检测余额,够用扣款,不够用提示,用户行为都要记录日志
    8 用户可以随时退出,退出时,打印已购买商品和余额

    借鉴了老师在day011中的代码框架,添加了部分代码。

    项目的结构如下。

    项目的目录结构如下。

    项目的运行结果展示

    待改进的地方

    1.  未做到单点登录
    2.  日志的信息不够详细
    3.  项目的健壮性,输入校验等等,有待提高

    代码如下。

    #/bin/start.py
    import sys,os
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BASE_DIR)
    
    from core import src
    
    if __name__ == '__main__':
        src.run()
    

      

    #/conf/setting.py
    
    import os
    
    BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    DB_PATH=os.path.join(BASE_DIR,'db','db.json')
    LOG_PATH=os.path.join(BASE_DIR,'log','access.log')
    LOGIN_TIMEOUT=3
    
    """
    logging配置
    """
    # 定义三种日志输出格式
    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配置字典
    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': LOG_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)传递
            },
        },
    }
    

      

    #/core/src.py
    
    from conf import settings
    from lib import common
    import time
    
    logger=common.get_logger(__name__)
    
    current_user={'user':None,'login_time':None,'timeout':int(settings.LOGIN_TIMEOUT)}
    
    
    def auth(func):
        def wrapper(*args,**kwargs):
            if current_user['user']:
                interval=time.time()-current_user['login_time']
                if interval < current_user['timeout']:
                    return func(*args,**kwargs)
            name = input('name>>: ')
            db=common.conn_db()
            if db.get(name):   #已注册用户的登录流程
                if db.get(name).get('locked'):
                    logger.warning('该用户已被锁定')
                    print ('该用户已被锁定')
                else:
                    logging_error_times = 0
    
                    while True:
                        if logging_error_times >= 3:
                            logger.warning('密码输入错误3次,该用户已被')
                            db[name]['locked'] = 1
                            common.save_db(db)
                            break
                        password = input('password>>:')
                        if password == db.get(name).get('password'):
                            logger.info('登录成功')
                            print('登录成功')
                            current_user['user'] = name
                            current_user['login_time'] = time.time()
                            return func(*args, **kwargs)
                        else:
                            logger.warning('密码错误')
                            logging_error_times += 1
    
            else:           #注册
                is_register = input('是否注册? (Y/N)')
                if is_register in ['Y','y']:
                    password = input('password>>')
                    db[name] = {"password":password, "money":0, "locked":0}
                    logger.info("登录成功")
                    print('登录成功')
                    current_user['user'] = name
                    current_user['login_time'] = time.time()
                    common.save_db(db)
                    return func(*args, **kwargs)
                else:
                    logger.info('用户不注册')
        return wrapper
    
    
    @auth
    def buy():
        db = common.conn_db()
        money = db.get(current_user['user']).get('money')
        print ('目前账户有%d元' %money)
        items_dict = {'item1':1, 'item2':2}
        print (items_dict.keys())
        items_bought_dic = {}
        while True:
            item_buy = input('buy which(Q退出)?>>').strip()
            item_buy_split = item_buy.split(' ')
            #print (item_buy_split[0], item_buy_split[1])
            if item_buy_split[0] in ['q', 'Q']:
                db[current_user['user']]['money'] = money
                common.save_db(db)
                print('你买了:',items_bought_dic)
                print('账户余额:',money)
                break
            elif item_buy_split[0] in items_dict:
                item, item_num = item_buy_split[0], item_buy_split[1]
                item_price = items_dict[item] * int(item_num)
                print(item,':',item_num,'共花了%d'%item_price)
                if item_price <= money:
                    money -= item_price
                    print ('购买成功,还有%d元'%money)
                    if item in items_bought_dic:
                        items_bought_dic[item] += item_num
                    else:
                        items_bought_dic[item] = item_num
                else:
                    print ('余额不足')
            else:
                print ('请输入:【商量名称】 【商品数量】')
    
    
    @auth
    def withdraw():
        db = common.conn_db()
        money = db.get(current_user['user']).get('money')
        print ('账户余额%d元' %money)
        withdraw_num = int(input('取多少钱?'))
        if withdraw_num <= money:
            money -= withdraw_num
            db[current_user['user']]['money'] = money
            common.save_db(db)
            print ('取现成功,账户余额%d' % money)
        else:
            print ('账户余额不足')
    
    @auth
    def repay():
        db = common.conn_db()
        money = db.get(current_user['user']).get('money')
        print('账户余额%d元' % money)
        repay_num = int(input('还款数量? '))
        money += repay_num
        db[current_user['user']]['money'] = money
        common.save_db(db)
        print('还款成功,你还有%d' % (money))
    
    
    @auth
    def run():
    
        print('''
    1. 取现
    2. 还款
    3. 消费
    Q. 退出
        ''')
        while True:
            choice = input('>>: ').strip()
            if not choice:continue
            if choice == '1':
                withdraw()
            if choice == '2':
                repay()
            if choice == '3':
                buy()
            if choice in ['Q','q']:
                quit()
    

      

    #/db/db.json
    {"user1": {"password": "111", "money": 2705, "locked": 0}, "user2": {"password": "111", "money": 30000, "locked": 0}, "user3": {"password": "111", "money": 20000, "locked": 0}, "zjl": {"password": "111", "money": 0, "locked": 0}}
    

      

    #/lib/common.py
    
    from conf import settings
    import logging
    import logging.config
    import json
    
    def get_logger(name):
        logging.config.dictConfig(settings.LOGGING_DIC)  # 导入上面定义的logging配置
        logger = logging.getLogger(name)  # 生成一个log实例
        return logger
    
    def conn_db():
        db_path=settings.DB_PATH
        dic=json.load(open(db_path,'r',encoding='utf-8'))
        return dic
    
    def save_db(dic):
        db_path = settings.DB_PATH
        json.dump(dic, open(db_path, 'w', encoding='utf-8'))
    

      

    日志的截图

  • 相关阅读:
    Linux关闭You have new mail in /var/spool/mail/root提示
    表单验证提交内容不能为空的几种方法
    CSS选择器的优先级
    SQL Server BCP 资料导入导出
    软考数据库-系统开发与软件工程
    软考数据库-无损联接分解
    软考数据库-数据结构
    反转字符串, 以单词反转句子
    数组中是否存在两数之和等于目标值
    栈 (Swift数组实现栈)
  • 原文地址:https://www.cnblogs.com/marathoner/p/10273662.html
Copyright © 2020-2023  润新知