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 srcif __name__ == '__main__':src.run()
#/conf/setting.pyimport osBASE_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.pyfrom conf import settings
from lib import common
import timelogger=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 = 0while True:if logging_error_times >= 3:logger.warning('密码输入错误3次,该用户已被')db[name]['locked'] = 1common.save_db(db)breakpassword = input('password>>:')if password == db.get(name).get('password'):logger.info('登录成功')print('登录成功')current_user['user'] = namecurrent_user['login_time'] = time.time()return func(*args, **kwargs)else:logger.warning('密码错误')logging_error_times += 1else: #注册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'] = namecurrent_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'] = moneycommon.save_db(db)print('你买了:',items_bought_dic)print('账户余额:',money)breakelif 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_priceprint ('购买成功,还有%d元'%money)if item in items_bought_dic:items_bought_dic[item] += item_numelse:items_bought_dic[item] = item_numelse: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_numdb[current_user['user']]['money'] = moneycommon.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_numdb[current_user['user']]['money'] = moneycommon.save_db(db)print('还款成功,你还有%d' % (money))@auth
def run():print('''
1. 取现
2. 还款
3. 消费
Q. 退出''')while True:choice = input('>>: ').strip()if not choice:continueif 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.pyfrom conf import settings
import logging
import logging.config
import jsondef get_logger(name):logging.config.dictConfig(settings.LOGGING_DIC) # 导入上面定义的logging配置logger = logging.getLogger(name) # 生成一个log实例return loggerdef conn_db():db_path=settings.DB_PATHdic=json.load(open(db_path,'r',encoding='utf-8'))return dicdef save_db(dic):db_path = settings.DB_PATHjson.dump(dic, open(db_path, 'w', encoding='utf-8'))
日志的截图