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'))
日志的截图